UNPKG

6.63 kBJavaScriptView Raw
1'use strict';
2
3function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
4
5var isBigNumber = require('./bignumber/isBigNumber');
6/**
7 * Clone an object
8 *
9 * clone(x)
10 *
11 * Can clone any primitive type, array, and object.
12 * If x has a function clone, this function will be invoked to clone the object.
13 *
14 * @param {*} x
15 * @return {*} clone
16 */
17
18
19exports.clone = function clone(x) {
20 var type = _typeof(x); // immutable primitive types
21
22
23 if (type === 'number' || type === 'string' || type === 'boolean' || x === null || x === undefined) {
24 return x;
25 } // use clone function of the object when available
26
27
28 if (typeof x.clone === 'function') {
29 return x.clone();
30 } // array
31
32
33 if (Array.isArray(x)) {
34 return x.map(function (value) {
35 return clone(value);
36 });
37 }
38
39 if (x instanceof Date) return new Date(x.valueOf());
40 if (isBigNumber(x)) return x; // bignumbers are immutable
41
42 if (x instanceof RegExp) throw new TypeError('Cannot clone ' + x); // TODO: clone a RegExp
43 // object
44
45 return exports.map(x, clone);
46};
47/**
48 * Apply map to all properties of an object
49 * @param {Object} object
50 * @param {function} callback
51 * @return {Object} Returns a copy of the object with mapped properties
52 */
53
54
55exports.map = function (object, callback) {
56 var clone = {};
57
58 for (var key in object) {
59 if (exports.hasOwnProperty(object, key)) {
60 clone[key] = callback(object[key]);
61 }
62 }
63
64 return clone;
65};
66/**
67 * Extend object a with the properties of object b
68 * @param {Object} a
69 * @param {Object} b
70 * @return {Object} a
71 */
72
73
74exports.extend = function (a, b) {
75 for (var prop in b) {
76 if (exports.hasOwnProperty(b, prop)) {
77 a[prop] = b[prop];
78 }
79 }
80
81 return a;
82};
83/**
84 * Deep extend an object a with the properties of object b
85 * @param {Object} a
86 * @param {Object} b
87 * @returns {Object}
88 */
89
90
91exports.deepExtend = function deepExtend(a, b) {
92 // TODO: add support for Arrays to deepExtend
93 if (Array.isArray(b)) {
94 throw new TypeError('Arrays are not supported by deepExtend');
95 }
96
97 for (var prop in b) {
98 if (exports.hasOwnProperty(b, prop)) {
99 if (b[prop] && b[prop].constructor === Object) {
100 if (a[prop] === undefined) {
101 a[prop] = {};
102 }
103
104 if (a[prop].constructor === Object) {
105 deepExtend(a[prop], b[prop]);
106 } else {
107 a[prop] = b[prop];
108 }
109 } else if (Array.isArray(b[prop])) {
110 throw new TypeError('Arrays are not supported by deepExtend');
111 } else {
112 a[prop] = b[prop];
113 }
114 }
115 }
116
117 return a;
118};
119/**
120 * Deep test equality of all fields in two pairs of arrays or objects.
121 * @param {Array | Object} a
122 * @param {Array | Object} b
123 * @returns {boolean}
124 */
125
126
127exports.deepEqual = function deepEqual(a, b) {
128 var prop, i, len;
129
130 if (Array.isArray(a)) {
131 if (!Array.isArray(b)) {
132 return false;
133 }
134
135 if (a.length !== b.length) {
136 return false;
137 }
138
139 for (i = 0, len = a.length; i < len; i++) {
140 if (!exports.deepEqual(a[i], b[i])) {
141 return false;
142 }
143 }
144
145 return true;
146 } else if (a instanceof Object) {
147 if (Array.isArray(b) || !(b instanceof Object)) {
148 return false;
149 }
150
151 for (prop in a) {
152 // noinspection JSUnfilteredForInLoop
153 if (!exports.deepEqual(a[prop], b[prop])) {
154 return false;
155 }
156 }
157
158 for (prop in b) {
159 // noinspection JSUnfilteredForInLoop
160 if (!exports.deepEqual(a[prop], b[prop])) {
161 return false;
162 }
163 }
164
165 return true;
166 } else {
167 return a === b;
168 }
169};
170/**
171 * Test whether the current JavaScript engine supports Object.defineProperty
172 * @returns {boolean} returns true if supported
173 */
174
175
176exports.canDefineProperty = function () {
177 // test needed for broken IE8 implementation
178 try {
179 if (Object.defineProperty) {
180 Object.defineProperty({}, 'x', {
181 get: function get() {}
182 });
183 return true;
184 }
185 } catch (e) {}
186
187 return false;
188};
189/**
190 * Attach a lazy loading property to a constant.
191 * The given function `fn` is called once when the property is first requested.
192 * On older browsers (<IE8), the function will fall back to direct evaluation
193 * of the properties value.
194 * @param {Object} object Object where to add the property
195 * @param {string} prop Property name
196 * @param {Function} fn Function returning the property value. Called
197 * without arguments.
198 */
199
200
201exports.lazy = function (object, prop, fn) {
202 if (exports.canDefineProperty()) {
203 var _uninitialized = true;
204
205 var _value;
206
207 Object.defineProperty(object, prop, {
208 get: function get() {
209 if (_uninitialized) {
210 _value = fn();
211 _uninitialized = false;
212 }
213
214 return _value;
215 },
216 set: function set(value) {
217 _value = value;
218 _uninitialized = false;
219 },
220 configurable: true,
221 enumerable: true
222 });
223 } else {
224 // fall back to immediate evaluation
225 object[prop] = fn();
226 }
227};
228/**
229 * Traverse a path into an object.
230 * When a namespace is missing, it will be created
231 * @param {Object} object
232 * @param {string} path A dot separated string like 'name.space'
233 * @return {Object} Returns the object at the end of the path
234 */
235
236
237exports.traverse = function (object, path) {
238 var obj = object;
239
240 if (path) {
241 var names = path.split('.');
242
243 for (var i = 0; i < names.length; i++) {
244 var name = names[i];
245
246 if (!(name in obj)) {
247 obj[name] = {};
248 }
249
250 obj = obj[name];
251 }
252 }
253
254 return obj;
255};
256/**
257 * A safe hasOwnProperty
258 * @param {Object} object
259 * @param {string} property
260 */
261
262
263exports.hasOwnProperty = function (object, property) {
264 return object && Object.hasOwnProperty.call(object, property);
265};
266/**
267 * Test whether an object is a factory. a factory has fields:
268 *
269 * - factory: function (type: Object, config: Object, load: function, typed: function [, math: Object]) (required)
270 * - name: string (optional)
271 * - path: string A dot separated path (optional)
272 * - math: boolean If true (false by default), the math namespace is passed
273 * as fifth argument of the factory function
274 *
275 * @param {*} object
276 * @returns {boolean}
277 */
278
279
280exports.isFactory = function (object) {
281 return object && typeof object.factory === 'function';
282};
\No newline at end of file