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 and
Kent C. Dodds
committed
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

+4-1
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

+60
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

+2
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

+3-3
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

+2-2
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

+17-17
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

+55
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

+1-1
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

+1-1
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

+1-1
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

test/divide-test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {divide} from '../src'
44
test('divide two numbers ', t => {
55
const number1 = 7
66
const number2 = 2
7-
const expected = 7/2
7+
const expected = 7 / 2
88
const actual = divide(number1, number2)
99
t.deepEqual(actual, expected)
1010
})

test/find.test.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
import test from 'ava'
2-
import { find } from '../src'
2+
import {find} from '../src'
33

44
test('find returns undefined if the input is not an instance of Array', t => {
5-
const original = { prop: 'test' }
5+
const original = {prop: 'test'}
66
const predicate = element => 'does nothing'
77
const expected = undefined
88
const actual = find(original, element => predicate(element))
99
t.deepEqual(actual, expected)
1010
})
1111

1212
test('find returns the first element that matches the given predicate', t => {
13-
const original = [{ a: 1, b: 2 }, { c: 3 }, { a: 1, c: 4 }]
13+
const original = [{a: 1, b: 2}, {c: 3}, {a: 1, c: 4}]
1414
const predicate = element => element.a === 1
15-
const expected = { a: 1, b: 2 }
15+
const expected = {a: 1, b: 2}
1616
const actual = find(original, element => predicate(element))
1717
t.deepEqual(actual, expected)
1818
})
1919

2020
test('find returns undefined if nothing matches the given predicate', t => {
21-
const original = [{ a: 1, b: 2 }, { c: 3 }, { a: 1, c: 4 }]
21+
const original = [{a: 1, b: 2}, {c: 3}, {a: 1, c: 4}]
2222
const predicate = element => element.d === 1
2323
const expected = undefined
2424
const actual = find(original, element => predicate(element))

test/gcd.test.js

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import test from 'ava'
22
import {gcd} from '../src'
33

4-
test("Get gcd for two integers", t => {
5-
const a = 4;
6-
const b = 64;
7-
const expected = 4;
8-
const actual = gcd(a, b);
9-
t.deepEqual(actual, expected)
10-
})
4+
test('Get gcd for two integers', t => {
5+
const a = 4
6+
const b = 64
7+
const expected = 4
8+
const actual = gcd(a, b)
9+
t.deepEqual(actual, expected)
10+
})

test/get-object-size.test.js

+26-26
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,34 @@
1-
import test from 'ava';
2-
import { getObjectSize } from '../src'
1+
import test from 'ava'
2+
import {getObjectSize} from '../src'
33

4-
test('returns zero for empty object', t=> {
5-
const testObject = {}
6-
const expected = 0
7-
const actual = getObjectSize(testObject)
8-
t.deepEqual(actual, expected)
4+
test('returns zero for empty object', t => {
5+
const testObject = {}
6+
const expected = 0
7+
const actual = getObjectSize(testObject)
8+
t.deepEqual(actual, expected)
99
})
10-
test('returns 5 for object with 5 keys', t=> {
11-
const testObject = {
12-
prop1: 'prop1',
13-
prop2: 'prop2',
14-
prop3: 'prop3',
15-
prop4: 'prop4',
16-
prop5: 'prop5',
17-
}
18-
const expected = 5
19-
const actual = getObjectSize(testObject)
20-
t.deepEqual(actual, expected)
10+
test('returns 5 for object with 5 keys', t => {
11+
const testObject = {
12+
prop1: 'prop1',
13+
prop2: 'prop2',
14+
prop3: 'prop3',
15+
prop4: 'prop4',
16+
prop5: 'prop5',
17+
}
18+
const expected = 5
19+
const actual = getObjectSize(testObject)
20+
t.deepEqual(actual, expected)
2121
})
2222
test('returns size of empty array', t => {
23-
const testArray = []
24-
const expected = 0
25-
const actual = getObjectSize(testArray)
26-
t.deepEqual(actual, expected)
23+
const testArray = []
24+
const expected = 0
25+
const actual = getObjectSize(testArray)
26+
t.deepEqual(actual, expected)
2727
})
2828
test('returns size of array with items', t => {
29-
const testArray = ['test', 'test2']
30-
const expected = 2
31-
const actual = getObjectSize(testArray)
32-
t.deepEqual(actual, expected)
29+
const testArray = ['test', 'test2']
30+
const expected = 2
31+
const actual = getObjectSize(testArray)
32+
t.deepEqual(actual, expected)
3333
})
3434

test/getMiddle.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import test from 'ava'
2-
import { getMiddle } from '../src'
2+
import {getMiddle} from '../src'
33

44
test('Gets middle character of given string with a length of uneven number of characters ', t => {
55
const string = 'rumpelstiltskin'

0 commit comments

Comments
 (0)