-
-
Notifications
You must be signed in to change notification settings - Fork 64
/
object.js
139 lines (125 loc) · 2.69 KB
/
object.js
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/**
* Utility functions for working with EcmaScript objects.
*
* @module object
*/
/**
* @return {Object<string,any>} obj
*/
export const create = () => Object.create(null)
/**
* Object.assign
*/
export const assign = Object.assign
/**
* @param {Object<string,any>} obj
*/
export const keys = Object.keys
/**
* @template V
* @param {{[k:string]:V}} obj
* @param {function(V,string):any} f
*/
export const forEach = (obj, f) => {
for (const key in obj) {
f(obj[key], key)
}
}
/**
* @todo implement mapToArray & map
*
* @template R
* @param {Object<string,any>} obj
* @param {function(any,string):R} f
* @return {Array<R>}
*/
export const map = (obj, f) => {
const results = []
for (const key in obj) {
results.push(f(obj[key], key))
}
return results
}
/**
* @deprecated use object.size instead
* @param {Object<string,any>} obj
* @return {number}
*/
export const length = obj => keys(obj).length
/**
* @param {Object<string,any>} obj
* @return {number}
*/
export const size = obj => keys(obj).length
/**
* @param {Object<string,any>} obj
* @param {function(any,string):boolean} f
* @return {boolean}
*/
export const some = (obj, f) => {
for (const key in obj) {
if (f(obj[key], key)) {
return true
}
}
return false
}
/**
* @param {Object|undefined} obj
*/
export const isEmpty = obj => {
// eslint-disable-next-line
for (const _k in obj) {
return false
}
return true
}
/**
* @param {Object<string,any>} obj
* @param {function(any,string):boolean} f
* @return {boolean}
*/
export const every = (obj, f) => {
for (const key in obj) {
if (!f(obj[key], key)) {
return false
}
}
return true
}
/**
* Calls `Object.prototype.hasOwnProperty`.
*
* @param {any} obj
* @param {string|symbol} key
* @return {boolean}
*/
export const hasProperty = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key)
/**
* @param {Object<string,any>} a
* @param {Object<string,any>} b
* @return {boolean}
*/
export const equalFlat = (a, b) => a === b || (size(a) === size(b) && every(a, (val, key) => (val !== undefined || hasProperty(b, key)) && b[key] === val))
/**
* Make an object immutable. This hurts performance and is usually not needed if you perform good
* coding practices.
*/
export const freeze = Object.freeze
/**
* Make an object and all its children immutable.
* This *really* hurts performance and is usually not needed if you perform good coding practices.
*
* @template {any} T
* @param {T} o
* @return {Readonly<T>}
*/
export const deepFreeze = (o) => {
for (const key in o) {
const c = o[key]
if (typeof c === 'object' || typeof c === 'function') {
deepFreeze(o[key])
}
}
return freeze(o)
}