index.js 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009
  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. /** Used as the `TypeError` message for "Functions" methods. */
  10. var FUNC_ERROR_TEXT = 'Expected a function';
  11. /** Used to stand-in for `undefined` hash values. */
  12. var HASH_UNDEFINED = '__lodash_hash_undefined__';
  13. /** Used as references for various `Number` constants. */
  14. var INFINITY = 1 / 0;
  15. /** `Object#toString` result references. */
  16. var funcTag = '[object Function]',
  17. genTag = '[object GeneratorFunction]',
  18. symbolTag = '[object Symbol]';
  19. /** Used to match property names within property paths. */
  20. var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
  21. reIsPlainProp = /^\w*$/,
  22. reLeadingDot = /^\./,
  23. rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
  24. /**
  25. * Used to match `RegExp`
  26. * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
  27. */
  28. var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
  29. /** Used to match backslashes in property paths. */
  30. var reEscapeChar = /\\(\\)?/g;
  31. /** Used to detect host constructors (Safari). */
  32. var reIsHostCtor = /^\[object .+?Constructor\]$/;
  33. /** Detect free variable `global` from Node.js. */
  34. var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
  35. /** Detect free variable `self`. */
  36. var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
  37. /** Used as a reference to the global object. */
  38. var root = freeGlobal || freeSelf || Function('return this')();
  39. /**
  40. * Gets the value at `key` of `object`.
  41. *
  42. * @private
  43. * @param {Object} [object] The object to query.
  44. * @param {string} key The key of the property to get.
  45. * @returns {*} Returns the property value.
  46. */
  47. function getValue(object, key) {
  48. return object == null ? undefined : object[key];
  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. */
  57. function 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. /** Used for built-in method references. */
  69. var arrayProto = Array.prototype,
  70. funcProto = Function.prototype,
  71. objectProto = Object.prototype;
  72. /** Used to detect overreaching core-js shims. */
  73. var coreJsData = root['__core-js_shared__'];
  74. /** Used to detect methods masquerading as native. */
  75. var maskSrcKey = (function() {
  76. var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
  77. return uid ? ('Symbol(src)_1.' + uid) : '';
  78. }());
  79. /** Used to resolve the decompiled source of functions. */
  80. var funcToString = funcProto.toString;
  81. /** Used to check objects for own properties. */
  82. var hasOwnProperty = objectProto.hasOwnProperty;
  83. /**
  84. * Used to resolve the
  85. * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
  86. * of values.
  87. */
  88. var objectToString = objectProto.toString;
  89. /** Used to detect if a method is native. */
  90. var reIsNative = RegExp('^' +
  91. funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
  92. .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
  93. );
  94. /** Built-in value references. */
  95. var Symbol = root.Symbol,
  96. splice = arrayProto.splice;
  97. /* Built-in method references that are verified to be native. */
  98. var Map = getNative(root, 'Map'),
  99. nativeCreate = getNative(Object, 'create');
  100. /** Used to convert symbols to primitives and strings. */
  101. var symbolProto = Symbol ? Symbol.prototype : undefined,
  102. symbolToString = symbolProto ? symbolProto.toString : undefined;
  103. /**
  104. * Creates a hash object.
  105. *
  106. * @private
  107. * @constructor
  108. * @param {Array} [entries] The key-value pairs to cache.
  109. */
  110. function Hash(entries) {
  111. var index = -1,
  112. length = entries ? entries.length : 0;
  113. this.clear();
  114. while (++index < length) {
  115. var entry = entries[index];
  116. this.set(entry[0], entry[1]);
  117. }
  118. }
  119. /**
  120. * Removes all key-value entries from the hash.
  121. *
  122. * @private
  123. * @name clear
  124. * @memberOf Hash
  125. */
  126. function hashClear() {
  127. this.__data__ = nativeCreate ? nativeCreate(null) : {};
  128. }
  129. /**
  130. * Removes `key` and its value from the hash.
  131. *
  132. * @private
  133. * @name delete
  134. * @memberOf Hash
  135. * @param {Object} hash The hash to modify.
  136. * @param {string} key The key of the value to remove.
  137. * @returns {boolean} Returns `true` if the entry was removed, else `false`.
  138. */
  139. function hashDelete(key) {
  140. return this.has(key) && delete this.__data__[key];
  141. }
  142. /**
  143. * Gets the hash value for `key`.
  144. *
  145. * @private
  146. * @name get
  147. * @memberOf Hash
  148. * @param {string} key The key of the value to get.
  149. * @returns {*} Returns the entry value.
  150. */
  151. function hashGet(key) {
  152. var data = this.__data__;
  153. if (nativeCreate) {
  154. var result = data[key];
  155. return result === HASH_UNDEFINED ? undefined : result;
  156. }
  157. return hasOwnProperty.call(data, key) ? data[key] : undefined;
  158. }
  159. /**
  160. * Checks if a hash value for `key` exists.
  161. *
  162. * @private
  163. * @name has
  164. * @memberOf Hash
  165. * @param {string} key The key of the entry to check.
  166. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
  167. */
  168. function hashHas(key) {
  169. var data = this.__data__;
  170. return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key);
  171. }
  172. /**
  173. * Sets the hash `key` to `value`.
  174. *
  175. * @private
  176. * @name set
  177. * @memberOf Hash
  178. * @param {string} key The key of the value to set.
  179. * @param {*} value The value to set.
  180. * @returns {Object} Returns the hash instance.
  181. */
  182. function hashSet(key, value) {
  183. var data = this.__data__;
  184. data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
  185. return this;
  186. }
  187. // Add methods to `Hash`.
  188. Hash.prototype.clear = hashClear;
  189. Hash.prototype['delete'] = hashDelete;
  190. Hash.prototype.get = hashGet;
  191. Hash.prototype.has = hashHas;
  192. Hash.prototype.set = hashSet;
  193. /**
  194. * Creates an list cache object.
  195. *
  196. * @private
  197. * @constructor
  198. * @param {Array} [entries] The key-value pairs to cache.
  199. */
  200. function ListCache(entries) {
  201. var index = -1,
  202. length = entries ? entries.length : 0;
  203. this.clear();
  204. while (++index < length) {
  205. var entry = entries[index];
  206. this.set(entry[0], entry[1]);
  207. }
  208. }
  209. /**
  210. * Removes all key-value entries from the list cache.
  211. *
  212. * @private
  213. * @name clear
  214. * @memberOf ListCache
  215. */
  216. function listCacheClear() {
  217. this.__data__ = [];
  218. }
  219. /**
  220. * Removes `key` and its value from the list cache.
  221. *
  222. * @private
  223. * @name delete
  224. * @memberOf ListCache
  225. * @param {string} key The key of the value to remove.
  226. * @returns {boolean} Returns `true` if the entry was removed, else `false`.
  227. */
  228. function listCacheDelete(key) {
  229. var data = this.__data__,
  230. index = assocIndexOf(data, key);
  231. if (index < 0) {
  232. return false;
  233. }
  234. var lastIndex = data.length - 1;
  235. if (index == lastIndex) {
  236. data.pop();
  237. } else {
  238. splice.call(data, index, 1);
  239. }
  240. return true;
  241. }
  242. /**
  243. * Gets the list cache value for `key`.
  244. *
  245. * @private
  246. * @name get
  247. * @memberOf ListCache
  248. * @param {string} key The key of the value to get.
  249. * @returns {*} Returns the entry value.
  250. */
  251. function listCacheGet(key) {
  252. var data = this.__data__,
  253. index = assocIndexOf(data, key);
  254. return index < 0 ? undefined : data[index][1];
  255. }
  256. /**
  257. * Checks if a list cache value for `key` exists.
  258. *
  259. * @private
  260. * @name has
  261. * @memberOf ListCache
  262. * @param {string} key The key of the entry to check.
  263. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
  264. */
  265. function listCacheHas(key) {
  266. return assocIndexOf(this.__data__, key) > -1;
  267. }
  268. /**
  269. * Sets the list cache `key` to `value`.
  270. *
  271. * @private
  272. * @name set
  273. * @memberOf ListCache
  274. * @param {string} key The key of the value to set.
  275. * @param {*} value The value to set.
  276. * @returns {Object} Returns the list cache instance.
  277. */
  278. function listCacheSet(key, value) {
  279. var data = this.__data__,
  280. index = assocIndexOf(data, key);
  281. if (index < 0) {
  282. data.push([key, value]);
  283. } else {
  284. data[index][1] = value;
  285. }
  286. return this;
  287. }
  288. // Add methods to `ListCache`.
  289. ListCache.prototype.clear = listCacheClear;
  290. ListCache.prototype['delete'] = listCacheDelete;
  291. ListCache.prototype.get = listCacheGet;
  292. ListCache.prototype.has = listCacheHas;
  293. ListCache.prototype.set = listCacheSet;
  294. /**
  295. * Creates a map cache object to store key-value pairs.
  296. *
  297. * @private
  298. * @constructor
  299. * @param {Array} [entries] The key-value pairs to cache.
  300. */
  301. function MapCache(entries) {
  302. var index = -1,
  303. length = entries ? entries.length : 0;
  304. this.clear();
  305. while (++index < length) {
  306. var entry = entries[index];
  307. this.set(entry[0], entry[1]);
  308. }
  309. }
  310. /**
  311. * Removes all key-value entries from the map.
  312. *
  313. * @private
  314. * @name clear
  315. * @memberOf MapCache
  316. */
  317. function mapCacheClear() {
  318. this.__data__ = {
  319. 'hash': new Hash,
  320. 'map': new (Map || ListCache),
  321. 'string': new Hash
  322. };
  323. }
  324. /**
  325. * Removes `key` and its value from the map.
  326. *
  327. * @private
  328. * @name delete
  329. * @memberOf MapCache
  330. * @param {string} key The key of the value to remove.
  331. * @returns {boolean} Returns `true` if the entry was removed, else `false`.
  332. */
  333. function mapCacheDelete(key) {
  334. return getMapData(this, key)['delete'](key);
  335. }
  336. /**
  337. * Gets the map value for `key`.
  338. *
  339. * @private
  340. * @name get
  341. * @memberOf MapCache
  342. * @param {string} key The key of the value to get.
  343. * @returns {*} Returns the entry value.
  344. */
  345. function mapCacheGet(key) {
  346. return getMapData(this, key).get(key);
  347. }
  348. /**
  349. * Checks if a map value for `key` exists.
  350. *
  351. * @private
  352. * @name has
  353. * @memberOf MapCache
  354. * @param {string} key The key of the entry to check.
  355. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
  356. */
  357. function mapCacheHas(key) {
  358. return getMapData(this, key).has(key);
  359. }
  360. /**
  361. * Sets the map `key` to `value`.
  362. *
  363. * @private
  364. * @name set
  365. * @memberOf MapCache
  366. * @param {string} key The key of the value to set.
  367. * @param {*} value The value to set.
  368. * @returns {Object} Returns the map cache instance.
  369. */
  370. function mapCacheSet(key, value) {
  371. getMapData(this, key).set(key, value);
  372. return this;
  373. }
  374. // Add methods to `MapCache`.
  375. MapCache.prototype.clear = mapCacheClear;
  376. MapCache.prototype['delete'] = mapCacheDelete;
  377. MapCache.prototype.get = mapCacheGet;
  378. MapCache.prototype.has = mapCacheHas;
  379. MapCache.prototype.set = mapCacheSet;
  380. /**
  381. * Gets the index at which the `key` is found in `array` of key-value pairs.
  382. *
  383. * @private
  384. * @param {Array} array The array to inspect.
  385. * @param {*} key The key to search for.
  386. * @returns {number} Returns the index of the matched value, else `-1`.
  387. */
  388. function assocIndexOf(array, key) {
  389. var length = array.length;
  390. while (length--) {
  391. if (eq(array[length][0], key)) {
  392. return length;
  393. }
  394. }
  395. return -1;
  396. }
  397. /**
  398. * The base implementation of `_.get` without support for default values.
  399. *
  400. * @private
  401. * @param {Object} object The object to query.
  402. * @param {Array|string} path The path of the property to get.
  403. * @returns {*} Returns the resolved value.
  404. */
  405. function baseGet(object, path) {
  406. path = isKey(path, object) ? [path] : castPath(path);
  407. var index = 0,
  408. length = path.length;
  409. while (object != null && index < length) {
  410. object = object[toKey(path[index++])];
  411. }
  412. return (index && index == length) ? object : undefined;
  413. }
  414. /**
  415. * The base implementation of `_.isNative` without bad shim checks.
  416. *
  417. * @private
  418. * @param {*} value The value to check.
  419. * @returns {boolean} Returns `true` if `value` is a native function,
  420. * else `false`.
  421. */
  422. function baseIsNative(value) {
  423. if (!isObject(value) || isMasked(value)) {
  424. return false;
  425. }
  426. var pattern = (isFunction(value) || isHostObject(value)) ? reIsNative : reIsHostCtor;
  427. return pattern.test(toSource(value));
  428. }
  429. /**
  430. * The base implementation of `_.slice` without an iteratee call guard.
  431. *
  432. * @private
  433. * @param {Array} array The array to slice.
  434. * @param {number} [start=0] The start position.
  435. * @param {number} [end=array.length] The end position.
  436. * @returns {Array} Returns the slice of `array`.
  437. */
  438. function baseSlice(array, start, end) {
  439. var index = -1,
  440. length = array.length;
  441. if (start < 0) {
  442. start = -start > length ? 0 : (length + start);
  443. }
  444. end = end > length ? length : end;
  445. if (end < 0) {
  446. end += length;
  447. }
  448. length = start > end ? 0 : ((end - start) >>> 0);
  449. start >>>= 0;
  450. var result = Array(length);
  451. while (++index < length) {
  452. result[index] = array[index + start];
  453. }
  454. return result;
  455. }
  456. /**
  457. * The base implementation of `_.toString` which doesn't convert nullish
  458. * values to empty strings.
  459. *
  460. * @private
  461. * @param {*} value The value to process.
  462. * @returns {string} Returns the string.
  463. */
  464. function baseToString(value) {
  465. // Exit early for strings to avoid a performance hit in some environments.
  466. if (typeof value == 'string') {
  467. return value;
  468. }
  469. if (isSymbol(value)) {
  470. return symbolToString ? symbolToString.call(value) : '';
  471. }
  472. var result = (value + '');
  473. return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
  474. }
  475. /**
  476. * The base implementation of `_.unset`.
  477. *
  478. * @private
  479. * @param {Object} object The object to modify.
  480. * @param {Array|string} path The path of the property to unset.
  481. * @returns {boolean} Returns `true` if the property is deleted, else `false`.
  482. */
  483. function baseUnset(object, path) {
  484. path = isKey(path, object) ? [path] : castPath(path);
  485. object = parent(object, path);
  486. var key = toKey(last(path));
  487. return !(object != null && hasOwnProperty.call(object, key)) || delete object[key];
  488. }
  489. /**
  490. * Casts `value` to a path array if it's not one.
  491. *
  492. * @private
  493. * @param {*} value The value to inspect.
  494. * @returns {Array} Returns the cast property path array.
  495. */
  496. function castPath(value) {
  497. return isArray(value) ? value : stringToPath(value);
  498. }
  499. /**
  500. * Gets the data for `map`.
  501. *
  502. * @private
  503. * @param {Object} map The map to query.
  504. * @param {string} key The reference key.
  505. * @returns {*} Returns the map data.
  506. */
  507. function getMapData(map, key) {
  508. var data = map.__data__;
  509. return isKeyable(key)
  510. ? data[typeof key == 'string' ? 'string' : 'hash']
  511. : data.map;
  512. }
  513. /**
  514. * Gets the native function at `key` of `object`.
  515. *
  516. * @private
  517. * @param {Object} object The object to query.
  518. * @param {string} key The key of the method to get.
  519. * @returns {*} Returns the function if it's native, else `undefined`.
  520. */
  521. function getNative(object, key) {
  522. var value = getValue(object, key);
  523. return baseIsNative(value) ? value : undefined;
  524. }
  525. /**
  526. * Checks if `value` is a property name and not a property path.
  527. *
  528. * @private
  529. * @param {*} value The value to check.
  530. * @param {Object} [object] The object to query keys on.
  531. * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
  532. */
  533. function isKey(value, object) {
  534. if (isArray(value)) {
  535. return false;
  536. }
  537. var type = typeof value;
  538. if (type == 'number' || type == 'symbol' || type == 'boolean' ||
  539. value == null || isSymbol(value)) {
  540. return true;
  541. }
  542. return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
  543. (object != null && value in Object(object));
  544. }
  545. /**
  546. * Checks if `value` is suitable for use as unique object key.
  547. *
  548. * @private
  549. * @param {*} value The value to check.
  550. * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
  551. */
  552. function isKeyable(value) {
  553. var type = typeof value;
  554. return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
  555. ? (value !== '__proto__')
  556. : (value === null);
  557. }
  558. /**
  559. * Checks if `func` has its source masked.
  560. *
  561. * @private
  562. * @param {Function} func The function to check.
  563. * @returns {boolean} Returns `true` if `func` is masked, else `false`.
  564. */
  565. function isMasked(func) {
  566. return !!maskSrcKey && (maskSrcKey in func);
  567. }
  568. /**
  569. * Gets the parent value at `path` of `object`.
  570. *
  571. * @private
  572. * @param {Object} object The object to query.
  573. * @param {Array} path The path to get the parent value of.
  574. * @returns {*} Returns the parent value.
  575. */
  576. function parent(object, path) {
  577. return path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
  578. }
  579. /**
  580. * Converts `string` to a property path array.
  581. *
  582. * @private
  583. * @param {string} string The string to convert.
  584. * @returns {Array} Returns the property path array.
  585. */
  586. var stringToPath = memoize(function(string) {
  587. string = toString(string);
  588. var result = [];
  589. if (reLeadingDot.test(string)) {
  590. result.push('');
  591. }
  592. string.replace(rePropName, function(match, number, quote, string) {
  593. result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
  594. });
  595. return result;
  596. });
  597. /**
  598. * Converts `value` to a string key if it's not a string or symbol.
  599. *
  600. * @private
  601. * @param {*} value The value to inspect.
  602. * @returns {string|symbol} Returns the key.
  603. */
  604. function toKey(value) {
  605. if (typeof value == 'string' || isSymbol(value)) {
  606. return value;
  607. }
  608. var result = (value + '');
  609. return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
  610. }
  611. /**
  612. * Converts `func` to its source code.
  613. *
  614. * @private
  615. * @param {Function} func The function to process.
  616. * @returns {string} Returns the source code.
  617. */
  618. function toSource(func) {
  619. if (func != null) {
  620. try {
  621. return funcToString.call(func);
  622. } catch (e) {}
  623. try {
  624. return (func + '');
  625. } catch (e) {}
  626. }
  627. return '';
  628. }
  629. /**
  630. * Gets the last element of `array`.
  631. *
  632. * @static
  633. * @memberOf _
  634. * @since 0.1.0
  635. * @category Array
  636. * @param {Array} array The array to query.
  637. * @returns {*} Returns the last element of `array`.
  638. * @example
  639. *
  640. * _.last([1, 2, 3]);
  641. * // => 3
  642. */
  643. function last(array) {
  644. var length = array ? array.length : 0;
  645. return length ? array[length - 1] : undefined;
  646. }
  647. /**
  648. * Creates a function that memoizes the result of `func`. If `resolver` is
  649. * provided, it determines the cache key for storing the result based on the
  650. * arguments provided to the memoized function. By default, the first argument
  651. * provided to the memoized function is used as the map cache key. The `func`
  652. * is invoked with the `this` binding of the memoized function.
  653. *
  654. * **Note:** The cache is exposed as the `cache` property on the memoized
  655. * function. Its creation may be customized by replacing the `_.memoize.Cache`
  656. * constructor with one whose instances implement the
  657. * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
  658. * method interface of `delete`, `get`, `has`, and `set`.
  659. *
  660. * @static
  661. * @memberOf _
  662. * @since 0.1.0
  663. * @category Function
  664. * @param {Function} func The function to have its output memoized.
  665. * @param {Function} [resolver] The function to resolve the cache key.
  666. * @returns {Function} Returns the new memoized function.
  667. * @example
  668. *
  669. * var object = { 'a': 1, 'b': 2 };
  670. * var other = { 'c': 3, 'd': 4 };
  671. *
  672. * var values = _.memoize(_.values);
  673. * values(object);
  674. * // => [1, 2]
  675. *
  676. * values(other);
  677. * // => [3, 4]
  678. *
  679. * object.a = 2;
  680. * values(object);
  681. * // => [1, 2]
  682. *
  683. * // Modify the result cache.
  684. * values.cache.set(object, ['a', 'b']);
  685. * values(object);
  686. * // => ['a', 'b']
  687. *
  688. * // Replace `_.memoize.Cache`.
  689. * _.memoize.Cache = WeakMap;
  690. */
  691. function memoize(func, resolver) {
  692. if (typeof func != 'function' || (resolver && typeof resolver != 'function')) {
  693. throw new TypeError(FUNC_ERROR_TEXT);
  694. }
  695. var memoized = function() {
  696. var args = arguments,
  697. key = resolver ? resolver.apply(this, args) : args[0],
  698. cache = memoized.cache;
  699. if (cache.has(key)) {
  700. return cache.get(key);
  701. }
  702. var result = func.apply(this, args);
  703. memoized.cache = cache.set(key, result);
  704. return result;
  705. };
  706. memoized.cache = new (memoize.Cache || MapCache);
  707. return memoized;
  708. }
  709. // Assign cache to `_.memoize`.
  710. memoize.Cache = MapCache;
  711. /**
  712. * Performs a
  713. * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
  714. * comparison between two values to determine if they are equivalent.
  715. *
  716. * @static
  717. * @memberOf _
  718. * @since 4.0.0
  719. * @category Lang
  720. * @param {*} value The value to compare.
  721. * @param {*} other The other value to compare.
  722. * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
  723. * @example
  724. *
  725. * var object = { 'a': 1 };
  726. * var other = { 'a': 1 };
  727. *
  728. * _.eq(object, object);
  729. * // => true
  730. *
  731. * _.eq(object, other);
  732. * // => false
  733. *
  734. * _.eq('a', 'a');
  735. * // => true
  736. *
  737. * _.eq('a', Object('a'));
  738. * // => false
  739. *
  740. * _.eq(NaN, NaN);
  741. * // => true
  742. */
  743. function eq(value, other) {
  744. return value === other || (value !== value && other !== other);
  745. }
  746. /**
  747. * Checks if `value` is classified as an `Array` object.
  748. *
  749. * @static
  750. * @memberOf _
  751. * @since 0.1.0
  752. * @category Lang
  753. * @param {*} value The value to check.
  754. * @returns {boolean} Returns `true` if `value` is an array, else `false`.
  755. * @example
  756. *
  757. * _.isArray([1, 2, 3]);
  758. * // => true
  759. *
  760. * _.isArray(document.body.children);
  761. * // => false
  762. *
  763. * _.isArray('abc');
  764. * // => false
  765. *
  766. * _.isArray(_.noop);
  767. * // => false
  768. */
  769. var isArray = Array.isArray;
  770. /**
  771. * Checks if `value` is classified as a `Function` object.
  772. *
  773. * @static
  774. * @memberOf _
  775. * @since 0.1.0
  776. * @category Lang
  777. * @param {*} value The value to check.
  778. * @returns {boolean} Returns `true` if `value` is a function, else `false`.
  779. * @example
  780. *
  781. * _.isFunction(_);
  782. * // => true
  783. *
  784. * _.isFunction(/abc/);
  785. * // => false
  786. */
  787. function isFunction(value) {
  788. // The use of `Object#toString` avoids issues with the `typeof` operator
  789. // in Safari 8-9 which returns 'object' for typed array and other constructors.
  790. var tag = isObject(value) ? objectToString.call(value) : '';
  791. return tag == funcTag || tag == genTag;
  792. }
  793. /**
  794. * Checks if `value` is the
  795. * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
  796. * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
  797. *
  798. * @static
  799. * @memberOf _
  800. * @since 0.1.0
  801. * @category Lang
  802. * @param {*} value The value to check.
  803. * @returns {boolean} Returns `true` if `value` is an object, else `false`.
  804. * @example
  805. *
  806. * _.isObject({});
  807. * // => true
  808. *
  809. * _.isObject([1, 2, 3]);
  810. * // => true
  811. *
  812. * _.isObject(_.noop);
  813. * // => true
  814. *
  815. * _.isObject(null);
  816. * // => false
  817. */
  818. function isObject(value) {
  819. var type = typeof value;
  820. return !!value && (type == 'object' || type == 'function');
  821. }
  822. /**
  823. * Checks if `value` is object-like. A value is object-like if it's not `null`
  824. * and has a `typeof` result of "object".
  825. *
  826. * @static
  827. * @memberOf _
  828. * @since 4.0.0
  829. * @category Lang
  830. * @param {*} value The value to check.
  831. * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
  832. * @example
  833. *
  834. * _.isObjectLike({});
  835. * // => true
  836. *
  837. * _.isObjectLike([1, 2, 3]);
  838. * // => true
  839. *
  840. * _.isObjectLike(_.noop);
  841. * // => false
  842. *
  843. * _.isObjectLike(null);
  844. * // => false
  845. */
  846. function isObjectLike(value) {
  847. return !!value && typeof value == 'object';
  848. }
  849. /**
  850. * Checks if `value` is classified as a `Symbol` primitive or object.
  851. *
  852. * @static
  853. * @memberOf _
  854. * @since 4.0.0
  855. * @category Lang
  856. * @param {*} value The value to check.
  857. * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
  858. * @example
  859. *
  860. * _.isSymbol(Symbol.iterator);
  861. * // => true
  862. *
  863. * _.isSymbol('abc');
  864. * // => false
  865. */
  866. function isSymbol(value) {
  867. return typeof value == 'symbol' ||
  868. (isObjectLike(value) && objectToString.call(value) == symbolTag);
  869. }
  870. /**
  871. * Converts `value` to a string. An empty string is returned for `null`
  872. * and `undefined` values. The sign of `-0` is preserved.
  873. *
  874. * @static
  875. * @memberOf _
  876. * @since 4.0.0
  877. * @category Lang
  878. * @param {*} value The value to process.
  879. * @returns {string} Returns the string.
  880. * @example
  881. *
  882. * _.toString(null);
  883. * // => ''
  884. *
  885. * _.toString(-0);
  886. * // => '-0'
  887. *
  888. * _.toString([1, 2, 3]);
  889. * // => '1,2,3'
  890. */
  891. function toString(value) {
  892. return value == null ? '' : baseToString(value);
  893. }
  894. /**
  895. * Removes the property at `path` of `object`.
  896. *
  897. * **Note:** This method mutates `object`.
  898. *
  899. * @static
  900. * @memberOf _
  901. * @since 4.0.0
  902. * @category Object
  903. * @param {Object} object The object to modify.
  904. * @param {Array|string} path The path of the property to unset.
  905. * @returns {boolean} Returns `true` if the property is deleted, else `false`.
  906. * @example
  907. *
  908. * var object = { 'a': [{ 'b': { 'c': 7 } }] };
  909. * _.unset(object, 'a[0].b.c');
  910. * // => true
  911. *
  912. * console.log(object);
  913. * // => { 'a': [{ 'b': {} }] };
  914. *
  915. * _.unset(object, ['a', '0', 'b', 'c']);
  916. * // => true
  917. *
  918. * console.log(object);
  919. * // => { 'a': [{ 'b': {} }] };
  920. */
  921. function unset(object, path) {
  922. return object == null ? true : baseUnset(object, path);
  923. }
  924. module.exports = unset;