PageRenderTime 75ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/ajax/libs//1.0.0/lodash.js

https://gitlab.com/Mirros/cdnjs
JavaScript | 1581 lines | 1081 code | 54 blank | 446 comment | 121 complexity | bca2790ba524497fde180d7f16c8e0cb MD5 | raw file
  1. /**
  2. * @license
  3. * Lo-Dash 1.0.0 (Custom Build) <http://lodash.com/>
  4. * Build: `lodash modern -o ./dist/lodash.js`
  5. * Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
  6. * Based on Underscore.js 1.4.4 <http://underscorejs.org/>
  7. * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
  8. * Available under MIT license <http://lodash.com/license>
  9. */
  10. ;(function(window, undefined) {
  11. /** Detect free variable `exports` */
  12. var freeExports = typeof exports == 'object' && exports;
  13. /** Detect free variable `global` and use it as `window` */
  14. var freeGlobal = typeof global == 'object' && global;
  15. if (freeGlobal.global === freeGlobal) {
  16. window = freeGlobal;
  17. }
  18. /** Used for array and object method references */
  19. var arrayRef = [],
  20. objectRef = {};
  21. /** Used to generate unique IDs */
  22. var idCounter = 0;
  23. /** Used internally to indicate various things */
  24. var indicatorObject = objectRef;
  25. /** Used by `cachedContains` as the default size when optimizations are enabled for large arrays */
  26. var largeArraySize = 30;
  27. /** Used to restore the original `_` reference in `noConflict` */
  28. var oldDash = window._;
  29. /** Used to match HTML entities */
  30. var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g;
  31. /** Used to match empty string literals in compiled template source */
  32. var reEmptyStringLeading = /\b__p \+= '';/g,
  33. reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
  34. reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
  35. /** Used to match regexp flags from their coerced string values */
  36. var reFlags = /\w*$/;
  37. /** Used to detect if a method is native */
  38. var reNative = RegExp('^' +
  39. (objectRef.valueOf + '')
  40. .replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
  41. .replace(/valueOf|for [^\]]+/g, '.+?') + '$'
  42. );
  43. /**
  44. * Used to match ES6 template delimiters
  45. * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6
  46. */
  47. var reEsTemplate = /\$\{((?:(?=\\?)\\?[\s\S])*?)\}/g;
  48. /** Used to match "interpolate" template delimiters */
  49. var reInterpolate = /<%=([\s\S]+?)%>/g;
  50. /** Used to ensure capturing order of template delimiters */
  51. var reNoMatch = /($^)/;
  52. /** Used to match HTML characters */
  53. var reUnescapedHtml = /[&<>"']/g;
  54. /** Used to match unescaped characters in compiled string literals */
  55. var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
  56. /** Used to make template sourceURLs easier to identify */
  57. var templateCounter = 0;
  58. /** Native method shortcuts */
  59. var ceil = Math.ceil,
  60. concat = arrayRef.concat,
  61. floor = Math.floor,
  62. getPrototypeOf = reNative.test(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,
  63. hasOwnProperty = objectRef.hasOwnProperty,
  64. push = arrayRef.push,
  65. toString = objectRef.toString;
  66. /* Native method shortcuts for methods with the same name as other `lodash` methods */
  67. var nativeBind = reNative.test(nativeBind = slice.bind) && nativeBind,
  68. nativeIsArray = reNative.test(nativeIsArray = Array.isArray) && nativeIsArray,
  69. nativeIsFinite = window.isFinite,
  70. nativeIsNaN = window.isNaN,
  71. nativeKeys = reNative.test(nativeKeys = Object.keys) && nativeKeys,
  72. nativeMax = Math.max,
  73. nativeMin = Math.min,
  74. nativeRandom = Math.random;
  75. /** `Object#toString` result shortcuts */
  76. var argsClass = '[object Arguments]',
  77. arrayClass = '[object Array]',
  78. boolClass = '[object Boolean]',
  79. dateClass = '[object Date]',
  80. funcClass = '[object Function]',
  81. numberClass = '[object Number]',
  82. objectClass = '[object Object]',
  83. regexpClass = '[object RegExp]',
  84. stringClass = '[object String]';
  85. /** Detect various environments */
  86. var isIeOpera = !!window.attachEvent,
  87. isV8 = nativeBind && !/\n|true/.test(nativeBind + isIeOpera);
  88. /* Detect if `Function#bind` exists and is inferred to be fast (all but V8) */
  89. var isBindFast = nativeBind && !isV8;
  90. /* Detect if `Object.keys` exists and is inferred to be fast (IE, Opera, V8) */
  91. var isKeysFast = nativeKeys && (isIeOpera || isV8);
  92. /** Used to identify object classifications that `_.clone` supports */
  93. var cloneableClasses = {};
  94. cloneableClasses[funcClass] = false;
  95. cloneableClasses[argsClass] = cloneableClasses[arrayClass] =
  96. cloneableClasses[boolClass] = cloneableClasses[dateClass] =
  97. cloneableClasses[numberClass] = cloneableClasses[objectClass] =
  98. cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true;
  99. /** Used to lookup a built-in constructor by [[Class]] */
  100. var ctorByClass = {};
  101. ctorByClass[arrayClass] = Array;
  102. ctorByClass[boolClass] = Boolean;
  103. ctorByClass[dateClass] = Date;
  104. ctorByClass[objectClass] = Object;
  105. ctorByClass[numberClass] = Number;
  106. ctorByClass[regexpClass] = RegExp;
  107. ctorByClass[stringClass] = String;
  108. /** Used to determine if values are of the language type Object */
  109. var objectTypes = {
  110. 'boolean': false,
  111. 'function': true,
  112. 'object': true,
  113. 'number': false,
  114. 'string': false,
  115. 'undefined': false
  116. };
  117. /** Used to escape characters for inclusion in compiled string literals */
  118. var stringEscapes = {
  119. '\\': '\\',
  120. "'": "'",
  121. '\n': 'n',
  122. '\r': 'r',
  123. '\t': 't',
  124. '\u2028': 'u2028',
  125. '\u2029': 'u2029'
  126. };
  127. /*--------------------------------------------------------------------------*/
  128. /**
  129. * Creates a `lodash` object, that wraps the given `value`, to enable method
  130. * chaining.
  131. *
  132. * In addition to Lo-Dash methods, wrappers also have the following `Array` methods:
  133. * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`,
  134. * and `unshift`
  135. *
  136. * The chainable wrapper functions are:
  137. * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`, `compose`,
  138. * `concat`, `countBy`, `debounce`, `defaults`, `defer`, `delay`, `difference`,
  139. * `filter`, `flatten`, `forEach`, `forIn`, `forOwn`, `functions`, `groupBy`,
  140. * `initial`, `intersection`, `invert`, `invoke`, `keys`, `map`, `max`, `memoize`,
  141. * `merge`, `min`, `object`, `omit`, `once`, `pairs`, `partial`, `partialRight`,
  142. * `pick`, `pluck`, `push`, `range`, `reject`, `rest`, `reverse`, `shuffle`,
  143. * `slice`, `sort`, `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`,
  144. * `union`, `uniq`, `unshift`, `values`, `where`, `without`, `wrap`, and `zip`
  145. *
  146. * The non-chainable wrapper functions are:
  147. * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `has`, `identity`,
  148. * `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`, `isEmpty`,
  149. * `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`, `isObject`,
  150. * `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`, `lastIndexOf`,
  151. * `mixin`, `noConflict`, `pop`, `random`, `reduce`, `reduceRight`, `result`,
  152. * `shift`, `size`, `some`, `sortedIndex`, `template`, `unescape`, and `uniqueId`
  153. *
  154. * The wrapper functions `first` and `last` return wrapped values when `n` is
  155. * passed, otherwise they return unwrapped values.
  156. *
  157. * @name _
  158. * @constructor
  159. * @category Chaining
  160. * @param {Mixed} value The value to wrap in a `lodash` instance.
  161. * @returns {Object} Returns a `lodash` instance.
  162. */
  163. function lodash(value) {
  164. // exit early if already wrapped, even if wrapped by a different `lodash` constructor
  165. if (value && typeof value == 'object' && value.__wrapped__) {
  166. return value;
  167. }
  168. // allow invoking `lodash` without the `new` operator
  169. if (!(this instanceof lodash)) {
  170. return new lodash(value);
  171. }
  172. this.__wrapped__ = value;
  173. }
  174. /**
  175. * By default, the template delimiters used by Lo-Dash are similar to those in
  176. * embedded Ruby (ERB). Change the following template settings to use alternative
  177. * delimiters.
  178. *
  179. * @static
  180. * @memberOf _
  181. * @type Object
  182. */
  183. lodash.templateSettings = {
  184. /**
  185. * Used to detect `data` property values to be HTML-escaped.
  186. *
  187. * @memberOf _.templateSettings
  188. * @type RegExp
  189. */
  190. 'escape': /<%-([\s\S]+?)%>/g,
  191. /**
  192. * Used to detect code to be evaluated.
  193. *
  194. * @memberOf _.templateSettings
  195. * @type RegExp
  196. */
  197. 'evaluate': /<%([\s\S]+?)%>/g,
  198. /**
  199. * Used to detect `data` property values to inject.
  200. *
  201. * @memberOf _.templateSettings
  202. * @type RegExp
  203. */
  204. 'interpolate': reInterpolate,
  205. /**
  206. * Used to reference the data object in the template text.
  207. *
  208. * @memberOf _.templateSettings
  209. * @type String
  210. */
  211. 'variable': '',
  212. /**
  213. * Used to import variables into the compiled template.
  214. *
  215. * @memberOf _.templateSettings
  216. * @type Object
  217. */
  218. 'imports': {
  219. /**
  220. * A reference to the `lodash` function.
  221. *
  222. * @memberOf _.templateSettings.imports
  223. * @type Function
  224. */
  225. '_': lodash
  226. }
  227. };
  228. /*--------------------------------------------------------------------------*/
  229. /**
  230. * The template used to create iterator functions.
  231. *
  232. * @private
  233. * @param {Obect} data The data object used to populate the text.
  234. * @returns {String} Returns the interpolated text.
  235. */
  236. var iteratorTemplate = function(obj) {
  237. var __p = 'var index, iterable = ' +
  238. (obj.firstArg ) +
  239. ', result = iterable;\nif (!iterable) return result;\n' +
  240. (obj.top ) +
  241. ';\n';
  242. if (obj.arrays) {
  243. __p += 'var length = iterable.length; index = -1;\nif (' +
  244. (obj.arrays ) +
  245. ') {\n while (++index < length) {\n ' +
  246. (obj.loop ) +
  247. '\n }\n}\nelse { ';
  248. } ;
  249. if (obj.isKeysFast && obj.useHas) {
  250. __p += '\n var ownIndex = -1,\n ownProps = objectTypes[typeof iterable] ? nativeKeys(iterable) : [],\n length = ownProps.length;\n\n while (++ownIndex < length) {\n index = ownProps[ownIndex];\n ' +
  251. (obj.loop ) +
  252. '\n } ';
  253. } else {
  254. __p += '\n for (index in iterable) {';
  255. if ( obj.useHas) {
  256. __p += '\n if (';
  257. if (obj.useHas) {
  258. __p += 'hasOwnProperty.call(iterable, index)';
  259. } ;
  260. __p += ') { ';
  261. } ;
  262. __p +=
  263. (obj.loop ) +
  264. '; ';
  265. if ( obj.useHas) {
  266. __p += '\n }';
  267. } ;
  268. __p += '\n } ';
  269. } ;
  270. if (obj.arrays) {
  271. __p += '\n}';
  272. } ;
  273. __p +=
  274. (obj.bottom ) +
  275. ';\nreturn result';
  276. return __p
  277. };
  278. /** Reusable iterator options for `assign` and `defaults` */
  279. var defaultsIteratorOptions = {
  280. 'args': 'object, source, guard',
  281. 'top':
  282. 'var args = arguments,\n' +
  283. ' argsIndex = 0,\n' +
  284. " argsLength = typeof guard == 'number' ? 2 : args.length;\n" +
  285. 'while (++argsIndex < argsLength) {\n' +
  286. ' iterable = args[argsIndex];\n' +
  287. ' if (iterable && objectTypes[typeof iterable]) {',
  288. 'loop': "if (typeof result[index] == 'undefined') result[index] = iterable[index]",
  289. 'bottom': ' }\n}'
  290. };
  291. /** Reusable iterator options shared by `each`, `forIn`, and `forOwn` */
  292. var eachIteratorOptions = {
  293. 'args': 'collection, callback, thisArg',
  294. 'top': "callback = callback && typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg)",
  295. 'arrays': "typeof length == 'number'",
  296. 'loop': 'if (callback(iterable[index], index, collection) === false) return result'
  297. };
  298. /** Reusable iterator options for `forIn` and `forOwn` */
  299. var forOwnIteratorOptions = {
  300. 'top': 'if (!objectTypes[typeof iterable]) return result;\n' + eachIteratorOptions.top,
  301. 'arrays': false
  302. };
  303. /*--------------------------------------------------------------------------*/
  304. /**
  305. * Creates a function optimized to search large arrays for a given `value`,
  306. * starting at `fromIndex`, using strict equality for comparisons, i.e. `===`.
  307. *
  308. * @private
  309. * @param {Array} array The array to search.
  310. * @param {Mixed} value The value to search for.
  311. * @param {Number} [fromIndex=0] The index to search from.
  312. * @param {Number} [largeSize=30] The length at which an array is considered large.
  313. * @returns {Boolean} Returns `true`, if `value` is found, else `false`.
  314. */
  315. function cachedContains(array, fromIndex, largeSize) {
  316. fromIndex || (fromIndex = 0);
  317. var length = array.length,
  318. isLarge = (length - fromIndex) >= (largeSize || largeArraySize);
  319. if (isLarge) {
  320. var cache = {},
  321. index = fromIndex - 1;
  322. while (++index < length) {
  323. // manually coerce `value` to a string because `hasOwnProperty`, in some
  324. // older versions of Firefox, coerces objects incorrectly
  325. var key = array[index] + '';
  326. (hasOwnProperty.call(cache, key) ? cache[key] : (cache[key] = [])).push(array[index]);
  327. }
  328. }
  329. return function(value) {
  330. if (isLarge) {
  331. var key = value + '';
  332. return hasOwnProperty.call(cache, key) && indexOf(cache[key], value) > -1;
  333. }
  334. return indexOf(array, value, fromIndex) > -1;
  335. }
  336. }
  337. /**
  338. * Used by `_.max` and `_.min` as the default `callback` when a given
  339. * `collection` is a string value.
  340. *
  341. * @private
  342. * @param {String} value The character to inspect.
  343. * @returns {Number} Returns the code unit of given character.
  344. */
  345. function charAtCallback(value) {
  346. return value.charCodeAt(0);
  347. }
  348. /**
  349. * Used by `sortBy` to compare transformed `collection` values, stable sorting
  350. * them in ascending order.
  351. *
  352. * @private
  353. * @param {Object} a The object to compare to `b`.
  354. * @param {Object} b The object to compare to `a`.
  355. * @returns {Number} Returns the sort order indicator of `1` or `-1`.
  356. */
  357. function compareAscending(a, b) {
  358. var ai = a.index,
  359. bi = b.index;
  360. a = a.criteria;
  361. b = b.criteria;
  362. // ensure a stable sort in V8 and other engines
  363. // http://code.google.com/p/v8/issues/detail?id=90
  364. if (a !== b) {
  365. if (a > b || typeof a == 'undefined') {
  366. return 1;
  367. }
  368. if (a < b || typeof b == 'undefined') {
  369. return -1;
  370. }
  371. }
  372. return ai < bi ? -1 : 1;
  373. }
  374. /**
  375. * Creates a function that, when called, invokes `func` with the `this` binding
  376. * of `thisArg` and prepends any `partialArgs` to the arguments passed to the
  377. * bound function.
  378. *
  379. * @private
  380. * @param {Function|String} func The function to bind or the method name.
  381. * @param {Mixed} [thisArg] The `this` binding of `func`.
  382. * @param {Array} partialArgs An array of arguments to be partially applied.
  383. * @param {Object} [rightIndicator] Used to indicate partially applying arguments from the right.
  384. * @returns {Function} Returns the new bound function.
  385. */
  386. function createBound(func, thisArg, partialArgs, rightIndicator) {
  387. var isFunc = isFunction(func),
  388. isPartial = !partialArgs,
  389. key = thisArg;
  390. // juggle arguments
  391. if (isPartial) {
  392. partialArgs = thisArg;
  393. }
  394. if (!isFunc) {
  395. thisArg = func;
  396. }
  397. function bound() {
  398. // `Function#bind` spec
  399. // http://es5.github.com/#x15.3.4.5
  400. var args = arguments,
  401. thisBinding = isPartial ? this : thisArg;
  402. if (!isFunc) {
  403. func = thisArg[key];
  404. }
  405. if (partialArgs.length) {
  406. args = args.length
  407. ? (args = slice(args), rightIndicator ? args.concat(partialArgs) : partialArgs.concat(args))
  408. : partialArgs;
  409. }
  410. if (this instanceof bound) {
  411. // ensure `new bound` is an instance of `bound` and `func`
  412. noop.prototype = func.prototype;
  413. thisBinding = new noop;
  414. noop.prototype = null;
  415. // mimic the constructor's `return` behavior
  416. // http://es5.github.com/#x13.2.2
  417. var result = func.apply(thisBinding, args);
  418. return isObject(result) ? result : thisBinding;
  419. }
  420. return func.apply(thisBinding, args);
  421. }
  422. return bound;
  423. }
  424. /**
  425. * Produces a callback bound to an optional `thisArg`. If `func` is a property
  426. * name, the created callback will return the property value for a given element.
  427. * If `func` is an object, the created callback will return `true` for elements
  428. * that contain the equivalent object properties, otherwise it will return `false`.
  429. *
  430. * @private
  431. * @param {Mixed} [func=identity] The value to convert to a callback.
  432. * @param {Mixed} [thisArg] The `this` binding of the created callback.
  433. * @param {Number} [argCount=3] The number of arguments the callback accepts.
  434. * @returns {Function} Returns a callback function.
  435. */
  436. function createCallback(func, thisArg, argCount) {
  437. if (func == null) {
  438. return identity;
  439. }
  440. var type = typeof func;
  441. if (type != 'function') {
  442. if (type != 'object') {
  443. return function(object) {
  444. return object[func];
  445. };
  446. }
  447. var props = keys(func);
  448. return function(object) {
  449. var length = props.length,
  450. result = false;
  451. while (length--) {
  452. if (!(result = isEqual(object[props[length]], func[props[length]], indicatorObject))) {
  453. break;
  454. }
  455. }
  456. return result;
  457. };
  458. }
  459. if (typeof thisArg != 'undefined') {
  460. if (argCount === 1) {
  461. return function(value) {
  462. return func.call(thisArg, value);
  463. };
  464. }
  465. if (argCount === 2) {
  466. return function(a, b) {
  467. return func.call(thisArg, a, b);
  468. };
  469. }
  470. if (argCount === 4) {
  471. return function(accumulator, value, index, object) {
  472. return func.call(thisArg, accumulator, value, index, object);
  473. };
  474. }
  475. return function(value, index, object) {
  476. return func.call(thisArg, value, index, object);
  477. };
  478. }
  479. return func;
  480. }
  481. /**
  482. * Creates compiled iteration functions.
  483. *
  484. * @private
  485. * @param {Object} [options1, options2, ...] The compile options object(s).
  486. * arrays - A string of code to determine if the iterable is an array or array-like.
  487. * useHas - A boolean to specify using `hasOwnProperty` checks in the object loop.
  488. * args - A string of comma separated arguments the iteration function will accept.
  489. * top - A string of code to execute before the iteration branches.
  490. * loop - A string of code to execute in the object loop.
  491. * bottom - A string of code to execute after the iteration branches.
  492. *
  493. * @returns {Function} Returns the compiled function.
  494. */
  495. function createIterator() {
  496. var data = {
  497. // support properties
  498. 'isKeysFast': isKeysFast,
  499. // iterator options
  500. 'arrays': 'isArray(iterable)',
  501. 'bottom': '',
  502. 'loop': '',
  503. 'top': '',
  504. 'useHas': true
  505. };
  506. // merge options into a template data object
  507. for (var object, index = 0; object = arguments[index]; index++) {
  508. for (var key in object) {
  509. data[key] = object[key];
  510. }
  511. }
  512. var args = data.args;
  513. data.firstArg = /^[^,]+/.exec(args)[0];
  514. // create the function factory
  515. var factory = Function(
  516. 'createCallback, hasOwnProperty, isArguments, isArray, isString, ' +
  517. 'objectTypes, nativeKeys',
  518. 'return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}'
  519. );
  520. // return the compiled function
  521. return factory(
  522. createCallback, hasOwnProperty, isArguments, isArray, isString,
  523. objectTypes, nativeKeys
  524. );
  525. }
  526. /**
  527. * A function compiled to iterate `arguments` objects, arrays, objects, and
  528. * strings consistenly across environments, executing the `callback` for each
  529. * element in the `collection`. The `callback` is bound to `thisArg` and invoked
  530. * with three arguments; (value, index|key, collection). Callbacks may exit
  531. * iteration early by explicitly returning `false`.
  532. *
  533. * @private
  534. * @type Function
  535. * @param {Array|Object|String} collection The collection to iterate over.
  536. * @param {Function} [callback=identity] The function called per iteration.
  537. * @param {Mixed} [thisArg] The `this` binding of `callback`.
  538. * @returns {Array|Object|String} Returns `collection`.
  539. */
  540. var each = createIterator(eachIteratorOptions);
  541. /**
  542. * Used by `template` to escape characters for inclusion in compiled
  543. * string literals.
  544. *
  545. * @private
  546. * @param {String} match The matched character to escape.
  547. * @returns {String} Returns the escaped character.
  548. */
  549. function escapeStringChar(match) {
  550. return '\\' + stringEscapes[match];
  551. }
  552. /**
  553. * Used by `escape` to convert characters to HTML entities.
  554. *
  555. * @private
  556. * @param {String} match The matched character to escape.
  557. * @returns {String} Returns the escaped character.
  558. */
  559. function escapeHtmlChar(match) {
  560. return htmlEscapes[match];
  561. }
  562. /**
  563. * Checks if `value` is a DOM node in IE < 9.
  564. *
  565. * @private
  566. * @param {Mixed} value The value to check.
  567. * @returns {Boolean} Returns `true` if the `value` is a DOM node, else `false`.
  568. */
  569. function isNode(value) {
  570. // IE < 9 presents DOM nodes as `Object` objects except they have `toString`
  571. // methods that are `typeof` "string" and still can coerce nodes to strings
  572. return typeof value.toString != 'function' && typeof (value + '') == 'string';
  573. }
  574. /**
  575. * A no-operation function.
  576. *
  577. * @private
  578. */
  579. function noop() {
  580. // no operation performed
  581. }
  582. /**
  583. * Slices the `collection` from the `start` index up to, but not including,
  584. * the `end` index.
  585. *
  586. * Note: This function is used, instead of `Array#slice`, to support node lists
  587. * in IE < 9 and to ensure dense arrays are returned.
  588. *
  589. * @private
  590. * @param {Array|Object|String} collection The collection to slice.
  591. * @param {Number} start The start index.
  592. * @param {Number} end The end index.
  593. * @returns {Array} Returns the new array.
  594. */
  595. function slice(array, start, end) {
  596. start || (start = 0);
  597. if (typeof end == 'undefined') {
  598. end = array ? array.length : 0;
  599. }
  600. var index = -1,
  601. length = end - start || 0,
  602. result = Array(length < 0 ? 0 : length);
  603. while (++index < length) {
  604. result[index] = array[start + index];
  605. }
  606. return result;
  607. }
  608. /**
  609. * Used by `unescape` to convert HTML entities to characters.
  610. *
  611. * @private
  612. * @param {String} match The matched character to unescape.
  613. * @returns {String} Returns the unescaped character.
  614. */
  615. function unescapeHtmlChar(match) {
  616. return htmlUnescapes[match];
  617. }
  618. /*--------------------------------------------------------------------------*/
  619. /**
  620. * Checks if `value` is an `arguments` object.
  621. *
  622. * @static
  623. * @memberOf _
  624. * @category Objects
  625. * @param {Mixed} value The value to check.
  626. * @returns {Boolean} Returns `true`, if the `value` is an `arguments` object, else `false`.
  627. * @example
  628. *
  629. * (function() { return _.isArguments(arguments); })(1, 2, 3);
  630. * // => true
  631. *
  632. * _.isArguments([1, 2, 3]);
  633. * // => false
  634. */
  635. function isArguments(value) {
  636. return toString.call(value) == argsClass;
  637. }
  638. /**
  639. * Iterates over `object`'s own and inherited enumerable properties, executing
  640. * the `callback` for each property. The `callback` is bound to `thisArg` and
  641. * invoked with three arguments; (value, key, object). Callbacks may exit iteration
  642. * early by explicitly returning `false`.
  643. *
  644. * @static
  645. * @memberOf _
  646. * @type Function
  647. * @category Objects
  648. * @param {Object} object The object to iterate over.
  649. * @param {Function} [callback=identity] The function called per iteration.
  650. * @param {Mixed} [thisArg] The `this` binding of `callback`.
  651. * @returns {Object} Returns `object`.
  652. * @example
  653. *
  654. * function Dog(name) {
  655. * this.name = name;
  656. * }
  657. *
  658. * Dog.prototype.bark = function() {
  659. * alert('Woof, woof!');
  660. * };
  661. *
  662. * _.forIn(new Dog('Dagny'), function(value, key) {
  663. * alert(key);
  664. * });
  665. * // => alerts 'name' and 'bark' (order is not guaranteed)
  666. */
  667. var forIn = createIterator(eachIteratorOptions, forOwnIteratorOptions, {
  668. 'useHas': false
  669. });
  670. /**
  671. * Iterates over an object's own enumerable properties, executing the `callback`
  672. * for each property. The `callback` is bound to `thisArg` and invoked with three
  673. * arguments; (value, key, object). Callbacks may exit iteration early by explicitly
  674. * returning `false`.
  675. *
  676. * @static
  677. * @memberOf _
  678. * @type Function
  679. * @category Objects
  680. * @param {Object} object The object to iterate over.
  681. * @param {Function} [callback=identity] The function called per iteration.
  682. * @param {Mixed} [thisArg] The `this` binding of `callback`.
  683. * @returns {Object} Returns `object`.
  684. * @example
  685. *
  686. * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
  687. * alert(key);
  688. * });
  689. * // => alerts '0', '1', and 'length' (order is not guaranteed)
  690. */
  691. var forOwn = createIterator(eachIteratorOptions, forOwnIteratorOptions);
  692. /**
  693. * Checks if `value` is an array.
  694. *
  695. * @static
  696. * @memberOf _
  697. * @category Objects
  698. * @param {Mixed} value The value to check.
  699. * @returns {Boolean} Returns `true`, if the `value` is an array, else `false`.
  700. * @example
  701. *
  702. * (function() { return _.isArray(arguments); })();
  703. * // => false
  704. *
  705. * _.isArray([1, 2, 3]);
  706. * // => true
  707. */
  708. var isArray = nativeIsArray || function(value) {
  709. // `instanceof` may cause a memory leak in IE 7 if `value` is a host object
  710. // http://ajaxian.com/archives/working-aroung-the-instanceof-memory-leak
  711. return value instanceof Array || toString.call(value) == arrayClass;
  712. };
  713. /**
  714. * Creates an array composed of the own enumerable property names of `object`.
  715. *
  716. * @static
  717. * @memberOf _
  718. * @category Objects
  719. * @param {Object} object The object to inspect.
  720. * @returns {Array} Returns a new array of property names.
  721. * @example
  722. *
  723. * _.keys({ 'one': 1, 'two': 2, 'three': 3 });
  724. * // => ['one', 'two', 'three'] (order is not guaranteed)
  725. */
  726. var keys = !nativeKeys ? shimKeys : function(object) {
  727. if (!isObject(object)) {
  728. return [];
  729. }
  730. return nativeKeys(object);
  731. };
  732. /**
  733. * A fallback implementation of `isPlainObject` that checks if a given `value`
  734. * is an object created by the `Object` constructor, assuming objects created
  735. * by the `Object` constructor have no inherited enumerable properties and that
  736. * there are no `Object.prototype` extensions.
  737. *
  738. * @private
  739. * @param {Mixed} value The value to check.
  740. * @returns {Boolean} Returns `true`, if `value` is a plain object, else `false`.
  741. */
  742. function shimIsPlainObject(value) {
  743. // avoid non-objects and false positives for `arguments` objects
  744. var result = false;
  745. if (!(value && typeof value == 'object') || isArguments(value)) {
  746. return result;
  747. }
  748. // check that the constructor is `Object` (i.e. `Object instanceof Object`)
  749. var ctor = value.constructor;
  750. if ((!isFunction(ctor)) || ctor instanceof ctor) {
  751. // In most environments an object's own properties are iterated before
  752. // its inherited properties. If the last iterated property is an object's
  753. // own property then there are no inherited enumerable properties.
  754. forIn(value, function(value, key) {
  755. result = key;
  756. });
  757. return result === false || hasOwnProperty.call(value, result);
  758. }
  759. return result;
  760. }
  761. /**
  762. * A fallback implementation of `Object.keys` that produces an array of the
  763. * given object's own enumerable property names.
  764. *
  765. * @private
  766. * @param {Object} object The object to inspect.
  767. * @returns {Array} Returns a new array of property names.
  768. */
  769. function shimKeys(object) {
  770. var result = [];
  771. forOwn(object, function(value, key) {
  772. result.push(key);
  773. });
  774. return result;
  775. }
  776. /**
  777. * Used to convert characters to HTML entities:
  778. *
  779. * Though the `>` character is escaped for symmetry, characters like `>` and `/`
  780. * don't require escaping in HTML and have no special meaning unless they're part
  781. * of a tag or an unquoted attribute value.
  782. * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact")
  783. */
  784. var htmlEscapes = {
  785. '&': '&amp;',
  786. '<': '&lt;',
  787. '>': '&gt;',
  788. '"': '&quot;',
  789. "'": '&#39;'
  790. };
  791. /** Used to convert HTML entities to characters */
  792. var htmlUnescapes = invert(htmlEscapes);
  793. /*--------------------------------------------------------------------------*/
  794. /**
  795. * Assigns own enumerable properties of source object(s) to the destination
  796. * object. Subsequent sources will overwrite propery assignments of previous
  797. * sources. If a `callback` function is passed, it will be executed to produce
  798. * the assigned values. The `callback` is bound to `thisArg` and invoked with
  799. * two arguments; (objectValue, sourceValue).
  800. *
  801. * @static
  802. * @memberOf _
  803. * @type Function
  804. * @alias extend
  805. * @category Objects
  806. * @param {Object} object The destination object.
  807. * @param {Object} [source1, source2, ...] The source objects.
  808. * @param {Function} [callback] The function to customize assigning values.
  809. * @param {Mixed} [thisArg] The `this` binding of `callback`.
  810. * @returns {Object} Returns the destination object.
  811. * @example
  812. *
  813. * _.assign({ 'name': 'moe' }, { 'age': 40 });
  814. * // => { 'name': 'moe', 'age': 40 }
  815. *
  816. * var defaults = _.partialRight(_.assign, function(a, b) {
  817. * return typeof a == 'undefined' ? b : a;
  818. * });
  819. *
  820. * var food = { 'name': 'apple' };
  821. * defaults(food, { 'name': 'banana', 'type': 'fruit' });
  822. * // => { 'name': 'apple', 'type': 'fruit' }
  823. */
  824. var assign = createIterator(defaultsIteratorOptions, {
  825. 'top':
  826. defaultsIteratorOptions.top.replace(';',
  827. ';\n' +
  828. 'if (argsLength > 2) {\n' +
  829. " if (typeof args[argsLength - 2] == 'function') {\n" +
  830. ' var callback = createCallback(args[--argsLength - 1], args[argsLength--], 2);\n' +
  831. " } else if (typeof args[argsLength - 1] == 'function') {\n" +
  832. ' callback = args[--argsLength];\n' +
  833. ' }\n' +
  834. '}'
  835. ),
  836. 'loop': 'result[index] = callback ? callback(result[index], iterable[index]) : iterable[index]'
  837. });
  838. /**
  839. * Creates a clone of `value`. If `deep` is `true`, nested objects will also
  840. * be cloned, otherwise they will be assigned by reference. If a `callback`
  841. * function is passed, it will be executed to produce the cloned values. If
  842. * `callback` returns `undefined`, cloning will be handled by the method instead.
  843. * The `callback` is bound to `thisArg` and invoked with one argument; (value).
  844. *
  845. * @static
  846. * @memberOf _
  847. * @category Objects
  848. * @param {Mixed} value The value to clone.
  849. * @param {Boolean} [deep=false] A flag to indicate a deep clone.
  850. * @param {Function} [callback] The function to customize cloning values.
  851. * @param {Mixed} [thisArg] The `this` binding of `callback`.
  852. * @param- {Array} [stackA=[]] Internally used to track traversed source objects.
  853. * @param- {Array} [stackB=[]] Internally used to associate clones with source counterparts.
  854. * @returns {Mixed} Returns the cloned `value`.
  855. * @example
  856. *
  857. * var stooges = [
  858. * { 'name': 'moe', 'age': 40 },
  859. * { 'name': 'larry', 'age': 50 }
  860. * ];
  861. *
  862. * var shallow = _.clone(stooges);
  863. * shallow[0] === stooges[0];
  864. * // => true
  865. *
  866. * var deep = _.clone(stooges, true);
  867. * deep[0] === stooges[0];
  868. * // => false
  869. *
  870. * _.mixin({
  871. * 'clone': _.partialRight(_.clone, function(value) {
  872. * return _.isElement(value) ? value.cloneNode(false) : undefined;
  873. * })
  874. * });
  875. *
  876. * var clone = _.clone(document.body);
  877. * clone.childNodes.length;
  878. * // => 0
  879. */
  880. function clone(value, deep, callback, thisArg, stackA, stackB) {
  881. var result = value;
  882. // allows working with "Collections" methods without using their `callback`
  883. // argument, `index|key`, for this method's `callback`
  884. if (typeof deep == 'function') {
  885. thisArg = callback;
  886. callback = deep;
  887. deep = false;
  888. }
  889. if (typeof callback == 'function') {
  890. callback = typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg, 1);
  891. result = callback(result);
  892. var done = typeof result != 'undefined';
  893. if (!done) {
  894. result = value;
  895. }
  896. }
  897. // inspect [[Class]]
  898. var isObj = isObject(result);
  899. if (isObj) {
  900. var className = toString.call(result);
  901. if (!cloneableClasses[className]) {
  902. return result;
  903. }
  904. var isArr = isArray(result);
  905. }
  906. // shallow clone
  907. if (!isObj || !deep) {
  908. return isObj && !done
  909. ? (isArr ? slice(result) : assign({}, result))
  910. : result;
  911. }
  912. var ctor = ctorByClass[className];
  913. switch (className) {
  914. case boolClass:
  915. case dateClass:
  916. return done ? result : new ctor(+result);
  917. case numberClass:
  918. case stringClass:
  919. return done ? result : new ctor(result);
  920. case regexpClass:
  921. return done ? result : ctor(result.source, reFlags.exec(result));
  922. }
  923. // check for circular references and return corresponding clone
  924. stackA || (stackA = []);
  925. stackB || (stackB = []);
  926. var length = stackA.length;
  927. while (length--) {
  928. if (stackA[length] == value) {
  929. return stackB[length];
  930. }
  931. }
  932. // init cloned object
  933. if (!done) {
  934. result = isArr ? ctor(result.length) : {};
  935. // add array properties assigned by `RegExp#exec`
  936. if (isArr) {
  937. if (hasOwnProperty.call(value, 'index')) {
  938. result.index = value.index;
  939. }
  940. if (hasOwnProperty.call(value, 'input')) {
  941. result.input = value.input;
  942. }
  943. }
  944. }
  945. // add the source value to the stack of traversed objects
  946. // and associate it with its clone
  947. stackA.push(value);
  948. stackB.push(result);
  949. // recursively populate clone (susceptible to call stack limits)
  950. (isArr ? forEach : forOwn)(done ? result : value, function(objValue, key) {
  951. result[key] = clone(objValue, deep, callback, undefined, stackA, stackB);
  952. });
  953. return result;
  954. }
  955. /**
  956. * Creates a deep clone of `value`. If a `callback` function is passed, it will
  957. * be executed to produce the cloned values. If `callback` returns the value it
  958. * was passed, cloning will be handled by the method instead. The `callback` is
  959. * bound to `thisArg` and invoked with one argument; (value).
  960. *
  961. * Note: This function is loosely based on the structured clone algorithm. Functions
  962. * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and
  963. * objects created by constructors other than `Object` are cloned to plain `Object` objects.
  964. * See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm.
  965. *
  966. * @static
  967. * @memberOf _
  968. * @category Objects
  969. * @param {Mixed} value The value to deep clone.
  970. * @param {Function} [callback] The function to customize cloning values.
  971. * @param {Mixed} [thisArg] The `this` binding of `callback`.
  972. * @returns {Mixed} Returns the deep cloned `value`.
  973. * @example
  974. *
  975. * var stooges = [
  976. * { 'name': 'moe', 'age': 40 },
  977. * { 'name': 'larry', 'age': 50 }
  978. * ];
  979. *
  980. * var deep = _.cloneDeep(stooges);
  981. * deep[0] === stooges[0];
  982. * // => false
  983. *
  984. * var view = {
  985. * 'label': 'docs',
  986. * 'node': element
  987. * };
  988. *
  989. * var clone = _.cloneDeep(view, function(value) {
  990. * return _.isElement(value) ? value.cloneNode(true) : value;
  991. * });
  992. *
  993. * clone.node == view.node;
  994. * // => false
  995. */
  996. function cloneDeep(value, callback, thisArg) {
  997. return clone(value, true, callback, thisArg);
  998. }
  999. /**
  1000. * Assigns own enumerable properties of source object(s) to the destination
  1001. * object for all destination properties that resolve to `undefined`. Once a
  1002. * property is set, additional defaults of the same property will be ignored.
  1003. *
  1004. * @static
  1005. * @memberOf _
  1006. * @type Function
  1007. * @category Objects
  1008. * @param {Object} object The destination object.
  1009. * @param {Object} [source1, source2, ...] The source objects.
  1010. * @param- {Object} [guard] Internally used to allow working with `_.reduce`
  1011. * without using its callback's `key` and `object` arguments as sources.
  1012. * @returns {Object} Returns the destination object.
  1013. * @example
  1014. *
  1015. * var food = { 'name': 'apple' };
  1016. * _.defaults(food, { 'name': 'banana', 'type': 'fruit' });
  1017. * // => { 'name': 'apple', 'type': 'fruit' }
  1018. */
  1019. var defaults = createIterator(defaultsIteratorOptions);
  1020. /**
  1021. * Creates a sorted array of all enumerable properties, own and inherited,
  1022. * of `object` that have function values.
  1023. *
  1024. * @static
  1025. * @memberOf _
  1026. * @alias methods
  1027. * @category Objects
  1028. * @param {Object} object The object to inspect.
  1029. * @returns {Array} Returns a new array of property names that have function values.
  1030. * @example
  1031. *
  1032. * _.functions(_);
  1033. * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
  1034. */
  1035. function functions(object) {
  1036. var result = [];
  1037. forIn(object, function(value, key) {
  1038. if (isFunction(value)) {
  1039. result.push(key);
  1040. }
  1041. });
  1042. return result.sort();
  1043. }
  1044. /**
  1045. * Checks if the specified object `property` exists and is a direct property,
  1046. * instead of an inherited property.
  1047. *
  1048. * @static
  1049. * @memberOf _
  1050. * @category Objects
  1051. * @param {Object} object The object to check.
  1052. * @param {String} property The property to check for.
  1053. * @returns {Boolean} Returns `true` if key is a direct property, else `false`.
  1054. * @example
  1055. *
  1056. * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
  1057. * // => true
  1058. */
  1059. function has(object, property) {
  1060. return object ? hasOwnProperty.call(object, property) : false;
  1061. }
  1062. /**
  1063. * Creates an object composed of the inverted keys and values of the given `object`.
  1064. *
  1065. * @static
  1066. * @memberOf _
  1067. * @category Objects
  1068. * @param {Object} object The object to invert.
  1069. * @returns {Object} Returns the created inverted object.
  1070. * @example
  1071. *
  1072. * _.invert({ 'first': 'moe', 'second': 'larry' });
  1073. * // => { 'moe': 'first', 'larry': 'second' } (order is not guaranteed)
  1074. */
  1075. function invert(object) {
  1076. var index = -1,
  1077. props = keys(object),
  1078. length = props.length,
  1079. result = {};
  1080. while (++index < length) {
  1081. var key = props[index];
  1082. result[object[key]] = key;
  1083. }
  1084. return result;
  1085. }
  1086. /**
  1087. * Checks if `value` is a boolean value.
  1088. *
  1089. * @static
  1090. * @memberOf _
  1091. * @category Objects
  1092. * @param {Mixed} value The value to check.
  1093. * @returns {Boolean} Returns `true`, if the `value` is a boolean value, else `false`.
  1094. * @example
  1095. *
  1096. * _.isBoolean(null);
  1097. * // => false
  1098. */
  1099. function isBoolean(value) {
  1100. return value === true || value === false || toString.call(value) == boolClass;
  1101. }
  1102. /**
  1103. * Checks if `value` is a date.
  1104. *
  1105. * @static
  1106. * @memberOf _
  1107. * @category Objects
  1108. * @param {Mixed} value The value to check.
  1109. * @returns {Boolean} Returns `true`, if the `value` is a date, else `false`.
  1110. * @example
  1111. *
  1112. * _.isDate(new Date);
  1113. * // => true
  1114. */
  1115. function isDate(value) {
  1116. return value instanceof Date || toString.call(value) == dateClass;
  1117. }
  1118. /**
  1119. * Checks if `value` is a DOM element.
  1120. *
  1121. * @static
  1122. * @memberOf _
  1123. * @category Objects
  1124. * @param {Mixed} value The value to check.
  1125. * @returns {Boolean} Returns `true`, if the `value` is a DOM element, else `false`.
  1126. * @example
  1127. *
  1128. * _.isElement(document.body);
  1129. * // => true
  1130. */
  1131. function isElement(value) {
  1132. return value ? value.nodeType === 1 : false;
  1133. }
  1134. /**
  1135. * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a
  1136. * length of `0` and objects with no own enumerable properties are considered
  1137. * "empty".
  1138. *
  1139. * @static
  1140. * @memberOf _
  1141. * @category Objects
  1142. * @param {Array|Object|String} value The value to inspect.
  1143. * @returns {Boolean} Returns `true`, if the `value` is empty, else `false`.
  1144. * @example
  1145. *
  1146. * _.isEmpty([1, 2, 3]);
  1147. * // => false
  1148. *
  1149. * _.isEmpty({});
  1150. * // => true
  1151. *
  1152. * _.isEmpty('');
  1153. * // => true
  1154. */
  1155. function isEmpty(value) {
  1156. var result = true;
  1157. if (!value) {
  1158. return result;
  1159. }
  1160. var className = toString.call(value),
  1161. length = value.length;
  1162. if ((className == arrayClass || className == stringClass ||
  1163. className == argsClass) ||
  1164. (className == objectClass && typeof length == 'number' && isFunction(value.splice))) {
  1165. return !length;
  1166. }
  1167. forOwn(value, function() {
  1168. return (result = false);
  1169. });
  1170. return result;
  1171. }
  1172. /**
  1173. * Performs a deep comparison between two values to determine if they are
  1174. * equivalent to each other. If `callback` is passed, it will be executed to
  1175. * compare values. If `callback` returns `undefined`, comparisons will be handled
  1176. * by the method instead. The `callback` is bound to `thisArg` and invoked with
  1177. * two arguments; (a, b).
  1178. *
  1179. * @static
  1180. * @memberOf _
  1181. * @category Objects
  1182. * @param {Mixed} a The value to compare.
  1183. * @param {Mixed} b The other value to compare.
  1184. * @param {Function} [callback] The function to customize comparing values.
  1185. * @param {Mixed} [thisArg] The `this` binding of `callback`.
  1186. * @param- {Object} [stackA=[]] Internally used track traversed `a` objects.
  1187. * @param- {Object} [stackB=[]] Internally used track traversed `b` objects.
  1188. * @returns {Boolean} Returns `true`, if the values are equvalent, else `false`.
  1189. * @example
  1190. *
  1191. * var moe = { 'name': 'moe', 'age': 40 };
  1192. * var copy = { 'name': 'moe', 'age': 40 };
  1193. *
  1194. * moe == copy;
  1195. * // => false
  1196. *
  1197. * _.isEqual(moe, copy);
  1198. * // => true
  1199. *
  1200. * var words = ['hello', 'goodbye'];
  1201. * var otherWords = ['hi', 'goodbye'];
  1202. *
  1203. * _.isEqual(words, otherWords, function(a, b) {
  1204. * var reGreet = /^(?:hello|hi)$/i,
  1205. * aGreet = _.isString(a) && reGreet.test(a),
  1206. * bGreet = _.isString(b) && reGreet.test(b);
  1207. *
  1208. * return (aGreet || bGreet) ? (aGreet == bGreet) : undefined;
  1209. * });
  1210. * // => true
  1211. */
  1212. function isEqual(a, b, callback, thisArg, stackA, stackB) {
  1213. // used to indicate that when comparing objects, `a` has at least the properties of `b`
  1214. var whereIndicator = callback === indicatorObject;
  1215. if (callback && !whereIndicator) {
  1216. callback = typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg, 2);
  1217. var result = callback(a, b);
  1218. if (typeof result != 'undefined') {
  1219. return !!result;
  1220. }
  1221. }
  1222. // exit early for identical values
  1223. if (a === b) {
  1224. // treat `+0` vs. `-0` as not equal
  1225. return a !== 0 || (1 / a == 1 / b);
  1226. }
  1227. var type = typeof a,
  1228. otherType = typeof b;
  1229. // exit early for unlike primitive values
  1230. if (a === a &&
  1231. (!a || (type != 'function' && type != 'object')) &&
  1232. (!b || (otherType != 'function' && otherType != 'object'))) {
  1233. return false;
  1234. }
  1235. // exit early for `null` and `undefined`, avoiding ES3's Function#call behavior
  1236. // http://es5.github.com/#x15.3.4.4
  1237. if (a == null || b == null) {
  1238. return a === b;
  1239. }
  1240. // compare [[Class]] names
  1241. var className = toString.call(a),
  1242. otherClass = toString.call(b);
  1243. if (className == argsClass) {
  1244. className = objectClass;
  1245. }
  1246. if (otherClass == argsClass) {
  1247. otherClass = objectClass;
  1248. }
  1249. if (className != otherClass) {
  1250. return false;
  1251. }
  1252. switch (className) {
  1253. case boolClass:
  1254. case dateClass:
  1255. // coerce dates and booleans to numbers, dates to milliseconds and booleans
  1256. // to `1` or `0`, treating invalid dates coerced to `NaN` as not equal
  1257. return +a == +b;
  1258. case numberClass:
  1259. // treat `NaN` vs. `NaN` as equal
  1260. return a != +a
  1261. ? b != +b
  1262. // but treat `+0` vs. `-0` as not equal
  1263. : (a == 0 ? (1 / a == 1 / b) : a == +b);
  1264. case regexpClass:
  1265. case stringClass:
  1266. // coerce regexes to strings (http://es5.github.com/#x15.10.6.4)
  1267. // treat string primitives and their corresponding object instances as equal
  1268. return a == b + '';
  1269. }
  1270. var isArr = className == arrayClass;
  1271. if (!isArr) {
  1272. // unwrap any `lodash` wrapped values
  1273. if (a.__wrapped__ || b.__wrapped__) {
  1274. return isEqual(a.__wrapped__ || a, b.__wrapped__ || b, callback, thisArg, stackA, stackB);
  1275. }
  1276. // exit for functions and DOM nodes
  1277. if (className != objectClass) {
  1278. return false;
  1279. }
  1280. // in older versions of Opera, `arguments` objects have `Array` constructors
  1281. var ctorA = a.constructor,
  1282. ctorB = b.constructor;
  1283. // non `Object` object instances with different constructors are not equal
  1284. if (ctorA != ctorB && !(
  1285. isFunction(ctorA) && ctorA instanceof ctorA &&
  1286. isFunction(ctorB) && ctorB instanceof ctorB
  1287. )) {
  1288. return false;
  1289. }
  1290. }
  1291. // assume cyclic structures are equal
  1292. // the algorithm for detecting cyclic structures is adapted from ES 5.1
  1293. // section 15.12.3, abstract operation `JO` (http://es5.github.com/#x15.12.3)
  1294. stackA || (stackA = []);
  1295. stackB || (stackB = []);
  1296. var length = stackA.length;
  1297. while (length--) {
  1298. if (stackA[length] == a) {
  1299. return stackB[length] == b;
  1300. }
  1301. }
  1302. var size = 0;
  1303. result = true;
  1304. // add `a` and `b` to the stack of traversed objects
  1305. stackA.push(a);
  1306. stackB.push(b);
  1307. // recursively compare objects and arrays (susceptible to call stack limits)
  1308. if (isArr) {
  1309. // compare lengths to determine if a deep comparison is necessary
  1310. size = b.length;
  1311. result = whereIndicator || size == a.length;
  1312. if (result) {
  1313. // deep compare the contents, ignoring non-numeric properties
  1314. while (size--) {
  1315. if (!(result = isEqual(a[size], b[size], callback, thisArg, stackA, stackB))) {
  1316. break;
  1317. }
  1318. }
  1319. }
  1320. return result;
  1321. }
  1322. // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys`
  1323. // which, in this case, is more costly
  1324. forIn(b, function(value, key, b) {
  1325. if (hasOwnProperty.call(b, key)) {
  1326. // count the number of properties.
  1327. size++;
  1328. // deep compare each property value.
  1329. return (result = hasOwnProperty.call(a, key) && isEqual(a[key], value, callback, thisArg, stackA, stackB));
  1330. }
  1331. });
  1332. if (result && !whereIndicator) {
  1333. // ensure both objects have the same number of properties
  1334. forIn(a, function(value, key, a) {
  1335. if (hasOwnProperty.call(a, key)) {
  1336. // `size` will be `-1` if `a` has more properties than `b`
  1337. return (result = --size > -1);
  1338. }
  1339. });
  1340. }
  1341. return result;
  1342. }
  1343. /**
  1344. * Checks if `value` is, or can be coerced to, a finite number.
  1345. *
  1346. * Note: This is not the same as native `isFinite`, which will return true for
  1347. * booleans and empty strings. See http://es5.github.com/#x15.1.2.5.
  1348. *
  1349. * @static
  1350. * @memberOf _
  1351. * @category Objects
  1352. * @param {Mixed} value The value to check.
  1353. * @returns {Boolean} Returns `true`, if the `value` is finite, else `false`.
  1354. * @example
  1355. *
  1356. * _.isFinite(-101);
  1357. * // => true
  1358. *
  1359. * _.isFinite('10');
  1360. * // => true
  1361. *
  1362. * _.isFinite(true);
  1363. * // => false
  1364. *
  1365. * _.isFinite('');
  1366. * // => false
  1367. *
  1368. * _.isFinite(Infinity);
  1369. * // => false
  1370. */
  1371. function isFinite(value) {
  1372. return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value));
  1373. }
  1374. /**
  1375. * Checks if `value` is a function.
  1376. *
  1377. * @static
  1378. * @memberOf _
  1379. * @category Objects
  1380. * @param {Mixed} value The value to check.
  1381. * @returns {Boolean} Returns `true`, if the `value` is a function, else `false`.
  1382. * @example
  1383. *
  1384. * _.isFunction(_);
  1385. * // => true
  1386. */
  1387. function isFunction(value) {
  1388. return typeof value == 'function';
  1389. }
  1390. // fallback for older versions of Chrome and Safari
  1391. if (isFunction(/x/)) {
  1392. isFunction = function(value) {
  1393. return value instanceof Function || toString.call(value) == funcClass;
  1394. };
  1395. }
  1396. /**
  1397. * Checks if `value` is the language type of Object.
  1398. * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
  1399. *
  1400. * @static
  1401. * @memberOf _
  1402. * @category Objects
  1403. * @param {Mixed} value The value to check.
  1404. * @returns {Boolean} Returns `true`, if the `value` is an object, else `false`.
  1405. * @example
  1406. *
  1407. * _.isObject({});
  1408. * // => true
  1409. *
  1410. * _.isObject([1, 2, 3]);
  1411. * // => true
  1412. *
  1413. * _.isObject(1);
  1414. * // => false
  1415. */
  1416. function isObject(value) {
  1417. // check if the value is the ECMAScript language type of Object
  1418. // http://es5.github.com/#x8
  1419. // and avoid a V8 bug
  1420. // http://code.google.com/p/v8/issues/detail?id=2291
  1421. return value ? objectTypes[typeof value] : false;
  1422. }
  1423. /**
  1424. * Checks if `value` is `NaN`.
  1425. *
  1426. * Note: This is not the same as native `isNaN`, which will return `true` for
  1427. * `undefined` and other values. See http://es5.github.com/#x15.1.2.4.
  1428. *
  1429. * @static
  1430. * @memberOf _
  1431. * @category Objects
  1432. * @param {Mixed} value The value to check.
  1433. * @returns {Boolean} Returns `true`, if the `value` is `NaN`, else `false`.
  1434. * @example
  1435. *
  1436. * _.isNaN(NaN);
  1437. * // => true
  1438. *
  1439. * _.isNaN(new Number(NaN));
  1440. * // => true
  1441. *
  1442. * isNaN(undefined);
  1443. * // => true
  1444. *
  1445. * _.isNaN(undefined);
  1446. * // => false
  1447. */
  1448. function isNaN(value) {
  1449. // `NaN` as a primitive is the only value that is not equal to itself
  1450. // (perform the [[Class]] check first to avoid errors with some host objects in IE)
  1451. return isNumber(value) && value != +value
  1452. }
  1453. /**
  1454. * Checks if `value` is `null`.
  1455. *
  1456. * @static
  1457. * @memberOf _
  1458. * @category Objects
  1459. * @param {Mixed} value The value to check.
  1460. * @returns {Boolean}