Skip to content
This repository was archived by the owner on Feb 20, 2019. It is now read-only.

Commit 38869bd

Browse files
TolseeKent C. Dodds
authored andcommitted
feat: add clone method (#238)
Closes #237 There seem to be lint fixes for other files as well. Hope won't be a problem.
1 parent 53137c5 commit 38869bd

38 files changed

+355
-235
lines changed

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,13 @@ This repository exists as a resource for people to learn how to contribute to op
1919
## Usage
2020

2121
```javascript
22-
import {flatten, snakeToCamel} from 'stack-overflow-copy-paste'
22+
import {flatten, snakeToCamel, clone} from 'stack-overflow-copy-paste'
2323

2424
flatten([[1, 2,], 3]) // [1, 2, 3]
2525
snakeToCamel('snake-case-string') // 'snakeCaseString'
26+
27+
const testObj = {a: 1, b: 2}
28+
const copyObj = clone(testObj)
2629
```
2730

2831
## LICENSE

src/clone.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* Handler functions
3+
*/
4+
const handlers = {
5+
handleDate: date => {
6+
// Handle Date
7+
const copy = new Date()
8+
copy.setTime(date.getTime())
9+
return copy
10+
},
11+
handleArray: array => {
12+
const {length} = array
13+
14+
// Init array
15+
const copy = array.constructor(length)
16+
17+
for (let i = 0; i < length; i++) {
18+
copy[i] = clone(array[i])
19+
}
20+
21+
return copy
22+
},
23+
handleObject: object => {
24+
// Also copy prototypes
25+
const copy = Object.create(Object.getPrototypeOf(object))
26+
27+
for (const attr in object) {
28+
if (object.hasOwnProperty(attr)) {
29+
copy[attr] = clone(object[attr])
30+
}
31+
}
32+
return copy
33+
},
34+
handle(object) {
35+
if (object instanceof Date) {
36+
return this.handleDate(object)
37+
} else if (object instanceof Array) {
38+
return this.handleArray(object)
39+
} else {
40+
return this.handleObject(object)
41+
}
42+
},
43+
}
44+
45+
/**
46+
* Original StackOverflow answer https://stackoverflow.com/a/728694/6880789
47+
* This function will return cloned value
48+
* It can handle primitive data-type, Date, Array and Object
49+
* @param {null|undefined|number|string|function|object} object - any type
50+
* @return {null|undefined|number|string|function|object} - any type
51+
*/
52+
function clone(object) {
53+
// Handle primitive data-types, null and undefined
54+
if (typeof object !== 'object' || object === null || typeof object === 'function') {
55+
return object
56+
}
57+
return handlers.handle(object)
58+
}
59+
60+
export default clone

src/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ import toPower from './to-power'
8989
import truncate from './truncate'
9090
import validateEmail from './validateEmail'
9191
import removeElementByIndex from './removeElementByIndex'
92+
import clone from './clone'
9293

9394
export {
9495
reverseArrayInPlace,
@@ -182,4 +183,5 @@ export {
182183
largest,
183184
hex2hsl,
184185
removeElementByIndex,
186+
clone,
185187
}

test/BitwiseAnd.test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import test from 'ava'
22
import {BitwiseAnd} from '../src'
33

44
test('Returns the Bitwise And of all the Array Elements', t => {
5-
const name1=[1,3,5]
6-
const actual = BitwiseAnd(name1)
7-
const expected=1
5+
const name1 = [1, 3, 5]
6+
const actual = BitwiseAnd(name1)
7+
const expected = 1
88
t.deepEqual(actual, expected)
99
})
1010

test/array-average.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import test from 'ava'
22
import {
3-
arrayAverage
3+
arrayAverage,
44
} from '../src'
55

66
test('Calculates the average of an array', t => {
77
const array = [1, 2, 3, 4]
88
const expected = 2.5
99
const actual = arrayAverage(array)
1010
t.deepEqual(actual, expected)
11-
})
11+
})

test/array-median.test.js

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,36 @@ import test from 'ava'
22
import {median} from '../src'
33

44
test('accepts only typeof array param', t => {
5-
const array = {}
6-
const expected = `${array} is not an array.`
7-
const actual = median(array)
8-
t.deepEqual(actual, expected)
5+
const array = {}
6+
const expected = `${array} is not an array.`
7+
const actual = median(array)
8+
t.deepEqual(actual, expected)
99
})
1010

1111
test('accepts only arrays with numeric items', t => {
12-
const array = ['hello', 'world', 5, false]
13-
const expected = `${array} contains non-numeric items.`
14-
const actual = median(array)
15-
t.deepEqual(actual, expected)
12+
const array = ['hello', 'world', 5, false]
13+
const expected = `${array} contains non-numeric items.`
14+
const actual = median(array)
15+
t.deepEqual(actual, expected)
1616
})
1717

1818
test('accepts only nonempty arrays', t => {
19-
const array = []
20-
const expected = `${array} has no items.`
21-
const actual = median(array)
22-
t.deepEqual(actual, expected)
19+
const array = []
20+
const expected = `${array} has no items.`
21+
const actual = median(array)
22+
t.deepEqual(actual, expected)
2323
})
2424

2525
test('finds the median of an array with odd number of items', t => {
26-
const array = [13, 2, 5]
27-
const expected = 5
28-
const actual = median(array)
29-
t.deepEqual(actual, expected)
26+
const array = [13, 2, 5]
27+
const expected = 5
28+
const actual = median(array)
29+
t.deepEqual(actual, expected)
3030
})
3131

3232
test('finds the median of an array with even number of items', t => {
3333
const array = [9, 25, 4, 1]
3434
const expected = 6.5
3535
const actual = median(array)
3636
t.deepEqual(actual, expected)
37-
})
37+
})

test/clone.test.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import test from 'ava'
2+
import {clone} from '../src'
3+
4+
test('Clone number', t => {
5+
const original = 1
6+
const cloned = clone(original)
7+
t.deepEqual(cloned, original)
8+
})
9+
10+
test('Clone string', t => {
11+
const original = 'test string'
12+
const cloned = clone(original)
13+
t.deepEqual(cloned, original)
14+
})
15+
16+
test('Clone array', t => {
17+
const original = [1, 2, 3]
18+
const cloned = clone(original)
19+
t.deepEqual(cloned, original)
20+
})
21+
22+
test('Date', t => {
23+
const original = new Date()
24+
const cloned = clone(original)
25+
t.deepEqual(cloned.getTime(), original.getTime())
26+
})
27+
28+
test('Clone object', t => {
29+
const original = {a: 'test', b: 'test'}
30+
const cloned = clone(original)
31+
t.deepEqual(cloned, original)
32+
})
33+
34+
test('Clone object with prototype', t => {
35+
const original = {a: 'test'}
36+
Object.setPrototypeOf(original, {testprop: 4})
37+
const cloned = clone(original)
38+
t.deepEqual(cloned.testprop, original.testprop)
39+
})
40+
41+
test('Clone function', t => {
42+
function original() {
43+
return 1
44+
}
45+
const cloned = clone(original)
46+
t.deepEqual(cloned(), original())
47+
})
48+
49+
test('Clone Map', t => {
50+
const original = new Map([['key', 'test'], ['a', 'b']])
51+
const cloned = clone(original)
52+
t.deepEqual(cloned, original)
53+
})
54+
55+

test/convertToRoman.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ test('convert to roman numeral', t => {
66
const expected = 'XXIV'
77
const actual = convertToRoman(object)
88
t.deepEqual(actual, expected)
9-
})
9+
})

test/cube.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ test('Cube a number ', t => {
66
const expected = 5 * 5 * 5
77
const actual = cube(number)
88
t.deepEqual(actual, expected)
9-
})
9+
})

test/dec2bin.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ test('throws error if number is less than zero', t => {
1313
//const actual = dec2bin(original)
1414
const error = t.throws(() => {
1515
dec2bin(original)
16-
},RangeError)
16+
}, RangeError)
1717
t.is(error.message, 'Input must be a positive integer')
1818
})
1919

0 commit comments

Comments
 (0)