UNPKG

17 kBJavaScriptView Raw
1/**
2 * lodash (Custom Build) <https://lodash.com/>
3 * Build: `lodash modularize exports="npm" -o ./`
4 * Copyright jQuery Foundation and other contributors <https://jquery.org/>
5 * Released under MIT license <https://lodash.com/license>
6 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
7 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
8 */
9
10/** Used as the `TypeError` message for "Functions" methods. */
11var FUNC_ERROR_TEXT = 'Expected a function';
12
13/** Used to stand-in for `undefined` hash values. */
14var HASH_UNDEFINED = '__lodash_hash_undefined__';
15
16/** `Object#toString` result references. */
17var funcTag = '[object Function]',
18 genTag = '[object GeneratorFunction]';
19
20/**
21 * Used to match `RegExp`
22 * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
23 */
24var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
25
26/** Used to detect host constructors (Safari). */
27var reIsHostCtor = /^\[object .+?Constructor\]$/;
28
29/** Detect free variable `global` from Node.js. */
30var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
31
32/** Detect free variable `self`. */
33var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
34
35/** Used as a reference to the global object. */
36var root = freeGlobal || freeSelf || Function('return this')();
37
38/**
39 * Gets the value at `key` of `object`.
40 *
41 * @private
42 * @param {Object} [object] The object to query.
43 * @param {string} key The key of the property to get.
44 * @returns {*} Returns the property value.
45 */
46function getValue(object, key) {
47 return object == null ? undefined : object[key];
48}
49
50/**
51 * Checks if `value` is a host object in IE < 9.
52 *
53 * @private
54 * @param {*} value The value to check.
55 * @returns {boolean} Returns `true` if `value` is a host object, else `false`.
56 */
57function isHostObject(value) {
58 // Many host objects are `Object` objects that can coerce to strings
59 // despite having improperly defined `toString` methods.
60 var result = false;
61 if (value != null && typeof value.toString != 'function') {
62 try {
63 result = !!(value + '');
64 } catch (e) {}
65 }
66 return result;
67}
68
69/** Used for built-in method references. */
70var arrayProto = Array.prototype,
71 funcProto = Function.prototype,
72 objectProto = Object.prototype;
73
74/** Used to detect overreaching core-js shims. */
75var coreJsData = root['__core-js_shared__'];
76
77/** Used to detect methods masquerading as native. */
78var maskSrcKey = (function() {
79 var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
80 return uid ? ('Symbol(src)_1.' + uid) : '';
81}());
82
83/** Used to resolve the decompiled source of functions. */
84var funcToString = funcProto.toString;
85
86/** Used to check objects for own properties. */
87var hasOwnProperty = objectProto.hasOwnProperty;
88
89/**
90 * Used to resolve the
91 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
92 * of values.
93 */
94var objectToString = objectProto.toString;
95
96/** Used to detect if a method is native. */
97var reIsNative = RegExp('^' +
98 funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
99 .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
100);
101
102/** Built-in value references. */
103var splice = arrayProto.splice;
104
105/* Built-in method references that are verified to be native. */
106var Map = getNative(root, 'Map'),
107 nativeCreate = getNative(Object, 'create');
108
109/**
110 * Creates a hash object.
111 *
112 * @private
113 * @constructor
114 * @param {Array} [entries] The key-value pairs to cache.
115 */
116function Hash(entries) {
117 var index = -1,
118 length = entries ? entries.length : 0;
119
120 this.clear();
121 while (++index < length) {
122 var entry = entries[index];
123 this.set(entry[0], entry[1]);
124 }
125}
126
127/**
128 * Removes all key-value entries from the hash.
129 *
130 * @private
131 * @name clear
132 * @memberOf Hash
133 */
134function hashClear() {
135 this.__data__ = nativeCreate ? nativeCreate(null) : {};
136}
137
138/**
139 * Removes `key` and its value from the hash.
140 *
141 * @private
142 * @name delete
143 * @memberOf Hash
144 * @param {Object} hash The hash to modify.
145 * @param {string} key The key of the value to remove.
146 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
147 */
148function hashDelete(key) {
149 return this.has(key) && delete this.__data__[key];
150}
151
152/**
153 * Gets the hash value for `key`.
154 *
155 * @private
156 * @name get
157 * @memberOf Hash
158 * @param {string} key The key of the value to get.
159 * @returns {*} Returns the entry value.
160 */
161function hashGet(key) {
162 var data = this.__data__;
163 if (nativeCreate) {
164 var result = data[key];
165 return result === HASH_UNDEFINED ? undefined : result;
166 }
167 return hasOwnProperty.call(data, key) ? data[key] : undefined;
168}
169
170/**
171 * Checks if a hash value for `key` exists.
172 *
173 * @private
174 * @name has
175 * @memberOf Hash
176 * @param {string} key The key of the entry to check.
177 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
178 */
179function hashHas(key) {
180 var data = this.__data__;
181 return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key);
182}
183
184/**
185 * Sets the hash `key` to `value`.
186 *
187 * @private
188 * @name set
189 * @memberOf Hash
190 * @param {string} key The key of the value to set.
191 * @param {*} value The value to set.
192 * @returns {Object} Returns the hash instance.
193 */
194function hashSet(key, value) {
195 var data = this.__data__;
196 data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
197 return this;
198}
199
200// Add methods to `Hash`.
201Hash.prototype.clear = hashClear;
202Hash.prototype['delete'] = hashDelete;
203Hash.prototype.get = hashGet;
204Hash.prototype.has = hashHas;
205Hash.prototype.set = hashSet;
206
207/**
208 * Creates an list cache object.
209 *
210 * @private
211 * @constructor
212 * @param {Array} [entries] The key-value pairs to cache.
213 */
214function ListCache(entries) {
215 var index = -1,
216 length = entries ? entries.length : 0;
217
218 this.clear();
219 while (++index < length) {
220 var entry = entries[index];
221 this.set(entry[0], entry[1]);
222 }
223}
224
225/**
226 * Removes all key-value entries from the list cache.
227 *
228 * @private
229 * @name clear
230 * @memberOf ListCache
231 */
232function listCacheClear() {
233 this.__data__ = [];
234}
235
236/**
237 * Removes `key` and its value from the list cache.
238 *
239 * @private
240 * @name delete
241 * @memberOf ListCache
242 * @param {string} key The key of the value to remove.
243 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
244 */
245function listCacheDelete(key) {
246 var data = this.__data__,
247 index = assocIndexOf(data, key);
248
249 if (index < 0) {
250 return false;
251 }
252 var lastIndex = data.length - 1;
253 if (index == lastIndex) {
254 data.pop();
255 } else {
256 splice.call(data, index, 1);
257 }
258 return true;
259}
260
261/**
262 * Gets the list cache value for `key`.
263 *
264 * @private
265 * @name get
266 * @memberOf ListCache
267 * @param {string} key The key of the value to get.
268 * @returns {*} Returns the entry value.
269 */
270function listCacheGet(key) {
271 var data = this.__data__,
272 index = assocIndexOf(data, key);
273
274 return index < 0 ? undefined : data[index][1];
275}
276
277/**
278 * Checks if a list cache value for `key` exists.
279 *
280 * @private
281 * @name has
282 * @memberOf ListCache
283 * @param {string} key The key of the entry to check.
284 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
285 */
286function listCacheHas(key) {
287 return assocIndexOf(this.__data__, key) > -1;
288}
289
290/**
291 * Sets the list cache `key` to `value`.
292 *
293 * @private
294 * @name set
295 * @memberOf ListCache
296 * @param {string} key The key of the value to set.
297 * @param {*} value The value to set.
298 * @returns {Object} Returns the list cache instance.
299 */
300function listCacheSet(key, value) {
301 var data = this.__data__,
302 index = assocIndexOf(data, key);
303
304 if (index < 0) {
305 data.push([key, value]);
306 } else {
307 data[index][1] = value;
308 }
309 return this;
310}
311
312// Add methods to `ListCache`.
313ListCache.prototype.clear = listCacheClear;
314ListCache.prototype['delete'] = listCacheDelete;
315ListCache.prototype.get = listCacheGet;
316ListCache.prototype.has = listCacheHas;
317ListCache.prototype.set = listCacheSet;
318
319/**
320 * Creates a map cache object to store key-value pairs.
321 *
322 * @private
323 * @constructor
324 * @param {Array} [entries] The key-value pairs to cache.
325 */
326function MapCache(entries) {
327 var index = -1,
328 length = entries ? entries.length : 0;
329
330 this.clear();
331 while (++index < length) {
332 var entry = entries[index];
333 this.set(entry[0], entry[1]);
334 }
335}
336
337/**
338 * Removes all key-value entries from the map.
339 *
340 * @private
341 * @name clear
342 * @memberOf MapCache
343 */
344function mapCacheClear() {
345 this.__data__ = {
346 'hash': new Hash,
347 'map': new (Map || ListCache),
348 'string': new Hash
349 };
350}
351
352/**
353 * Removes `key` and its value from the map.
354 *
355 * @private
356 * @name delete
357 * @memberOf MapCache
358 * @param {string} key The key of the value to remove.
359 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
360 */
361function mapCacheDelete(key) {
362 return getMapData(this, key)['delete'](key);
363}
364
365/**
366 * Gets the map value for `key`.
367 *
368 * @private
369 * @name get
370 * @memberOf MapCache
371 * @param {string} key The key of the value to get.
372 * @returns {*} Returns the entry value.
373 */
374function mapCacheGet(key) {
375 return getMapData(this, key).get(key);
376}
377
378/**
379 * Checks if a map value for `key` exists.
380 *
381 * @private
382 * @name has
383 * @memberOf MapCache
384 * @param {string} key The key of the entry to check.
385 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
386 */
387function mapCacheHas(key) {
388 return getMapData(this, key).has(key);
389}
390
391/**
392 * Sets the map `key` to `value`.
393 *
394 * @private
395 * @name set
396 * @memberOf MapCache
397 * @param {string} key The key of the value to set.
398 * @param {*} value The value to set.
399 * @returns {Object} Returns the map cache instance.
400 */
401function mapCacheSet(key, value) {
402 getMapData(this, key).set(key, value);
403 return this;
404}
405
406// Add methods to `MapCache`.
407MapCache.prototype.clear = mapCacheClear;
408MapCache.prototype['delete'] = mapCacheDelete;
409MapCache.prototype.get = mapCacheGet;
410MapCache.prototype.has = mapCacheHas;
411MapCache.prototype.set = mapCacheSet;
412
413/**
414 * Gets the index at which the `key` is found in `array` of key-value pairs.
415 *
416 * @private
417 * @param {Array} array The array to inspect.
418 * @param {*} key The key to search for.
419 * @returns {number} Returns the index of the matched value, else `-1`.
420 */
421function assocIndexOf(array, key) {
422 var length = array.length;
423 while (length--) {
424 if (eq(array[length][0], key)) {
425 return length;
426 }
427 }
428 return -1;
429}
430
431/**
432 * The base implementation of `_.isNative` without bad shim checks.
433 *
434 * @private
435 * @param {*} value The value to check.
436 * @returns {boolean} Returns `true` if `value` is a native function,
437 * else `false`.
438 */
439function baseIsNative(value) {
440 if (!isObject(value) || isMasked(value)) {
441 return false;
442 }
443 var pattern = (isFunction(value) || isHostObject(value)) ? reIsNative : reIsHostCtor;
444 return pattern.test(toSource(value));
445}
446
447/**
448 * Gets the data for `map`.
449 *
450 * @private
451 * @param {Object} map The map to query.
452 * @param {string} key The reference key.
453 * @returns {*} Returns the map data.
454 */
455function getMapData(map, key) {
456 var data = map.__data__;
457 return isKeyable(key)
458 ? data[typeof key == 'string' ? 'string' : 'hash']
459 : data.map;
460}
461
462/**
463 * Gets the native function at `key` of `object`.
464 *
465 * @private
466 * @param {Object} object The object to query.
467 * @param {string} key The key of the method to get.
468 * @returns {*} Returns the function if it's native, else `undefined`.
469 */
470function getNative(object, key) {
471 var value = getValue(object, key);
472 return baseIsNative(value) ? value : undefined;
473}
474
475/**
476 * Checks if `value` is suitable for use as unique object key.
477 *
478 * @private
479 * @param {*} value The value to check.
480 * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
481 */
482function isKeyable(value) {
483 var type = typeof value;
484 return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
485 ? (value !== '__proto__')
486 : (value === null);
487}
488
489/**
490 * Checks if `func` has its source masked.
491 *
492 * @private
493 * @param {Function} func The function to check.
494 * @returns {boolean} Returns `true` if `func` is masked, else `false`.
495 */
496function isMasked(func) {
497 return !!maskSrcKey && (maskSrcKey in func);
498}
499
500/**
501 * Converts `func` to its source code.
502 *
503 * @private
504 * @param {Function} func The function to process.
505 * @returns {string} Returns the source code.
506 */
507function toSource(func) {
508 if (func != null) {
509 try {
510 return funcToString.call(func);
511 } catch (e) {}
512 try {
513 return (func + '');
514 } catch (e) {}
515 }
516 return '';
517}
518
519/**
520 * Creates a function that memoizes the result of `func`. If `resolver` is
521 * provided, it determines the cache key for storing the result based on the
522 * arguments provided to the memoized function. By default, the first argument
523 * provided to the memoized function is used as the map cache key. The `func`
524 * is invoked with the `this` binding of the memoized function.
525 *
526 * **Note:** The cache is exposed as the `cache` property on the memoized
527 * function. Its creation may be customized by replacing the `_.memoize.Cache`
528 * constructor with one whose instances implement the
529 * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
530 * method interface of `delete`, `get`, `has`, and `set`.
531 *
532 * @static
533 * @memberOf _
534 * @since 0.1.0
535 * @category Function
536 * @param {Function} func The function to have its output memoized.
537 * @param {Function} [resolver] The function to resolve the cache key.
538 * @returns {Function} Returns the new memoized function.
539 * @example
540 *
541 * var object = { 'a': 1, 'b': 2 };
542 * var other = { 'c': 3, 'd': 4 };
543 *
544 * var values = _.memoize(_.values);
545 * values(object);
546 * // => [1, 2]
547 *
548 * values(other);
549 * // => [3, 4]
550 *
551 * object.a = 2;
552 * values(object);
553 * // => [1, 2]
554 *
555 * // Modify the result cache.
556 * values.cache.set(object, ['a', 'b']);
557 * values(object);
558 * // => ['a', 'b']
559 *
560 * // Replace `_.memoize.Cache`.
561 * _.memoize.Cache = WeakMap;
562 */
563function memoize(func, resolver) {
564 if (typeof func != 'function' || (resolver && typeof resolver != 'function')) {
565 throw new TypeError(FUNC_ERROR_TEXT);
566 }
567 var memoized = function() {
568 var args = arguments,
569 key = resolver ? resolver.apply(this, args) : args[0],
570 cache = memoized.cache;
571
572 if (cache.has(key)) {
573 return cache.get(key);
574 }
575 var result = func.apply(this, args);
576 memoized.cache = cache.set(key, result);
577 return result;
578 };
579 memoized.cache = new (memoize.Cache || MapCache);
580 return memoized;
581}
582
583// Assign cache to `_.memoize`.
584memoize.Cache = MapCache;
585
586/**
587 * Performs a
588 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
589 * comparison between two values to determine if they are equivalent.
590 *
591 * @static
592 * @memberOf _
593 * @since 4.0.0
594 * @category Lang
595 * @param {*} value The value to compare.
596 * @param {*} other The other value to compare.
597 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
598 * @example
599 *
600 * var object = { 'a': 1 };
601 * var other = { 'a': 1 };
602 *
603 * _.eq(object, object);
604 * // => true
605 *
606 * _.eq(object, other);
607 * // => false
608 *
609 * _.eq('a', 'a');
610 * // => true
611 *
612 * _.eq('a', Object('a'));
613 * // => false
614 *
615 * _.eq(NaN, NaN);
616 * // => true
617 */
618function eq(value, other) {
619 return value === other || (value !== value && other !== other);
620}
621
622/**
623 * Checks if `value` is classified as a `Function` object.
624 *
625 * @static
626 * @memberOf _
627 * @since 0.1.0
628 * @category Lang
629 * @param {*} value The value to check.
630 * @returns {boolean} Returns `true` if `value` is a function, else `false`.
631 * @example
632 *
633 * _.isFunction(_);
634 * // => true
635 *
636 * _.isFunction(/abc/);
637 * // => false
638 */
639function isFunction(value) {
640 // The use of `Object#toString` avoids issues with the `typeof` operator
641 // in Safari 8-9 which returns 'object' for typed array and other constructors.
642 var tag = isObject(value) ? objectToString.call(value) : '';
643 return tag == funcTag || tag == genTag;
644}
645
646/**
647 * Checks if `value` is the
648 * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
649 * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
650 *
651 * @static
652 * @memberOf _
653 * @since 0.1.0
654 * @category Lang
655 * @param {*} value The value to check.
656 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
657 * @example
658 *
659 * _.isObject({});
660 * // => true
661 *
662 * _.isObject([1, 2, 3]);
663 * // => true
664 *
665 * _.isObject(_.noop);
666 * // => true
667 *
668 * _.isObject(null);
669 * // => false
670 */
671function isObject(value) {
672 var type = typeof value;
673 return !!value && (type == 'object' || type == 'function');
674}
675
676module.exports = memoize;