PageRenderTime 27ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/ajax/libs/lodash.js/1.0.0/lodash.compat.js

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