-
Notifications
You must be signed in to change notification settings - Fork 39
/
util.ts
61 lines (57 loc) · 1.99 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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
export const hasOwnProperty = Object.prototype.hasOwnProperty
export function objectType(object: any) {
if (object === undefined) {
return 'undefined'
}
if (object === null) {
return 'null'
}
if (Array.isArray(object)) {
return 'array'
}
return typeof object
}
function isNonPrimitive(value: any): value is object {
// 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
return value != null && typeof value == 'object'
}
/**
Recursively copy a value.
@param source - should be a JavaScript primitive, Array, Date, 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 {
if (!isNonPrimitive(source)) {
// 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 as Array<any>).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
}
// Date
if (source.constructor == Date) {
const dateTarget: any = new Date(+source)
return dateTarget
}
// 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
}