PageRenderTime 26ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/ajax/libs//1.0.0-rc.2/lodash.js

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