forked from chbrown/rfc6902
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutil.ts
39 lines (37 loc) · 1.54 KB
/
util.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
const hasOwnProperty = Object.prototype.hasOwnProperty
/**
Recursively copy a value.
@param source - should be a JavaScript primitive, Array, or (plain old) Object.
@returns copy of source where every Array and Object have been recursively
reconstructed from their constituent elements
*/
export function clone<T extends any>(source: T): T {
// loose-equality checking for null is faster than strict checking for each of null/undefined/true/false
// checking null first, then calling typeof, is faster than vice-versa
if (source == null || typeof source != 'object') {
// short-circuiting is faster than a single return
return source
}
// x.constructor == Array is the fastest way to check if x is an Array
if (source.constructor == Array) {
// construction via imperative for-loop is faster than source.map(arrayVsObject)
const length = source.length
// setting the Array length during construction is faster than just `[]` or `new Array()`
const arrayTarget: any = new Array(length)
for (let i = 0; i < length; i++) {
arrayTarget[i] = clone(source[i])
}
return arrayTarget
}
// Object
const objectTarget: any = {}
// declaring the variable (with const) inside the loop is faster
for (const key in source) {
// hasOwnProperty costs a bit of performance, but it's semantically necessary
// using a global helper is MUCH faster than calling source.hasOwnProperty(key)
if (hasOwnProperty.call(source, key)) {
objectTarget[key] = clone(source[key])
}
}
return objectTarget
}