PageRenderTime 62ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

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

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