Initial commit
[yaffs-website] / node_modules / lodash / dist / lodash.compat.js
1 /**
2  * @license
3  * Lo-Dash 1.0.2 (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
12   /** Detect free variable `exports` */
13   var freeExports = typeof exports == 'object' && exports;
14
15   /** Detect free variable `module` */
16   var freeModule = typeof module == 'object' && module && module.exports == freeExports && module;
17
18   /** Detect free variable `global` and use it as `window` */
19   var freeGlobal = typeof global == 'object' && global;
20   if (freeGlobal.global === freeGlobal) {
21     window = freeGlobal;
22   }
23
24   /** Used for array and object method references */
25   var arrayRef = [],
26       objectRef = {};
27
28   /** Used to generate unique IDs */
29   var idCounter = 0;
30
31   /** Used internally to indicate various things */
32   var indicatorObject = objectRef;
33
34   /** Used by `cachedContains` as the default size when optimizations are enabled for large arrays */
35   var largeArraySize = 30;
36
37   /** Used to restore the original `_` reference in `noConflict` */
38   var oldDash = window._;
39
40   /** Used to match HTML entities */
41   var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g;
42
43   /** Used to match empty string literals in compiled template source */
44   var reEmptyStringLeading = /\b__p \+= '';/g,
45       reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
46       reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
47
48   /** Used to match regexp flags from their coerced string values */
49   var reFlags = /\w*$/;
50
51   /** Used to detect if a method is native */
52   var reNative = RegExp('^' +
53     (objectRef.valueOf + '')
54       .replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
55       .replace(/valueOf|for [^\]]+/g, '.+?') + '$'
56   );
57
58   /**
59    * Used to match ES6 template delimiters
60    * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6
61    */
62   var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
63
64   /** Used to match "interpolate" template delimiters */
65   var reInterpolate = /<%=([\s\S]+?)%>/g;
66
67   /** Used to ensure capturing order of template delimiters */
68   var reNoMatch = /($^)/;
69
70   /** Used to match HTML characters */
71   var reUnescapedHtml = /[&<>"']/g;
72
73   /** Used to match unescaped characters in compiled string literals */
74   var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
75
76   /** Used to fix the JScript [[DontEnum]] bug */
77   var shadowed = [
78     'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',
79     'toLocaleString', 'toString', 'valueOf'
80   ];
81
82   /** Used to make template sourceURLs easier to identify */
83   var templateCounter = 0;
84
85   /** Native method shortcuts */
86   var ceil = Math.ceil,
87       concat = arrayRef.concat,
88       floor = Math.floor,
89       getPrototypeOf = reNative.test(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,
90       hasOwnProperty = objectRef.hasOwnProperty,
91       push = arrayRef.push,
92       toString = objectRef.toString;
93
94   /* Native method shortcuts for methods with the same name as other `lodash` methods */
95   var nativeBind = reNative.test(nativeBind = slice.bind) && nativeBind,
96       nativeIsArray = reNative.test(nativeIsArray = Array.isArray) && nativeIsArray,
97       nativeIsFinite = window.isFinite,
98       nativeIsNaN = window.isNaN,
99       nativeKeys = reNative.test(nativeKeys = Object.keys) && nativeKeys,
100       nativeMax = Math.max,
101       nativeMin = Math.min,
102       nativeRandom = Math.random;
103
104   /** `Object#toString` result shortcuts */
105   var argsClass = '[object Arguments]',
106       arrayClass = '[object Array]',
107       boolClass = '[object Boolean]',
108       dateClass = '[object Date]',
109       funcClass = '[object Function]',
110       numberClass = '[object Number]',
111       objectClass = '[object Object]',
112       regexpClass = '[object RegExp]',
113       stringClass = '[object String]';
114
115   /** Detect various environments */
116   var isIeOpera = !!window.attachEvent,
117       isV8 = nativeBind && !/\n|true/.test(nativeBind + isIeOpera);
118
119   /* Detect if `Function#bind` exists and is inferred to be fast (all but V8) */
120   var isBindFast = nativeBind && !isV8;
121
122   /* Detect if `Object.keys` exists and is inferred to be fast (IE, Opera, V8) */
123   var isKeysFast = nativeKeys && (isIeOpera || isV8);
124
125   /**
126    * Detect the JScript [[DontEnum]] bug:
127    *
128    * In IE < 9 an objects own properties, shadowing non-enumerable ones, are
129    * made non-enumerable as well.
130    */
131   var hasDontEnumBug;
132
133   /**
134    * Detect if a `prototype` properties are enumerable by default:
135    *
136    * Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1
137    * (if the prototype or a property on the prototype has been set)
138    * incorrectly sets a function's `prototype` property [[Enumerable]]
139    * value to `true`.
140    */
141   var hasEnumPrototype;
142
143   /** Detect if own properties are iterated after inherited properties (IE < 9) */
144   var iteratesOwnLast;
145
146   /**
147    * Detect if `Array#shift` and `Array#splice` augment array-like objects
148    * incorrectly:
149    *
150    * Firefox < 10, IE compatibility mode, and IE < 9 have buggy Array `shift()`
151    * and `splice()` functions that fail to remove the last element, `value[0]`,
152    * of array-like objects even though the `length` property is set to `0`.
153    * The `shift()` method is buggy in IE 8 compatibility mode, while `splice()`
154    * is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9.
155    */
156   var hasObjectSpliceBug = (hasObjectSpliceBug = { '0': 1, 'length': 1 },
157     arrayRef.splice.call(hasObjectSpliceBug, 0, 1), hasObjectSpliceBug[0]);
158
159   /** Detect if `arguments` object indexes are non-enumerable (Firefox < 4, IE < 9, PhantomJS, Safari < 5.1) */
160   var nonEnumArgs = true;
161
162   (function() {
163     var props = [];
164     function ctor() { this.x = 1; }
165     ctor.prototype = { 'valueOf': 1, 'y': 1 };
166     for (var prop in new ctor) { props.push(prop); }
167     for (prop in arguments) { nonEnumArgs = !prop; }
168
169     hasDontEnumBug = !/valueOf/.test(props);
170     hasEnumPrototype = ctor.propertyIsEnumerable('prototype');
171     iteratesOwnLast = props[0] != 'x';
172   }(1));
173
174   /** Detect if `arguments` objects are `Object` objects (all but Opera < 10.5) */
175   var argsAreObjects = arguments.constructor == Object;
176
177   /** Detect if `arguments` objects [[Class]] is unresolvable (Firefox < 4, IE < 9) */
178   var noArgsClass = !isArguments(arguments);
179
180   /**
181    * Detect lack of support for accessing string characters by index:
182    *
183    * IE < 8 can't access characters by index and IE 8 can only access
184    * characters by index on string literals.
185    */
186   var noCharByIndex = ('x'[0] + Object('x')[0]) != 'xx';
187
188   /**
189    * Detect if a DOM node's [[Class]] is unresolvable (IE < 9)
190    * and that the JS engine won't error when attempting to coerce an object to
191    * a string without a `toString` function.
192    */
193   try {
194     var noNodeClass = toString.call(document) == objectClass && !({ 'toString': 0 } + '');
195   } catch(e) { }
196
197   /** Used to identify object classifications that `_.clone` supports */
198   var cloneableClasses = {};
199   cloneableClasses[funcClass] = false;
200   cloneableClasses[argsClass] = cloneableClasses[arrayClass] =
201   cloneableClasses[boolClass] = cloneableClasses[dateClass] =
202   cloneableClasses[numberClass] = cloneableClasses[objectClass] =
203   cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true;
204
205   /** Used to lookup a built-in constructor by [[Class]] */
206   var ctorByClass = {};
207   ctorByClass[arrayClass] = Array;
208   ctorByClass[boolClass] = Boolean;
209   ctorByClass[dateClass] = Date;
210   ctorByClass[objectClass] = Object;
211   ctorByClass[numberClass] = Number;
212   ctorByClass[regexpClass] = RegExp;
213   ctorByClass[stringClass] = String;
214
215   /** Used to determine if values are of the language type Object */
216   var objectTypes = {
217     'boolean': false,
218     'function': true,
219     'object': true,
220     'number': false,
221     'string': false,
222     'undefined': false
223   };
224
225   /** Used to escape characters for inclusion in compiled string literals */
226   var stringEscapes = {
227     '\\': '\\',
228     "'": "'",
229     '\n': 'n',
230     '\r': 'r',
231     '\t': 't',
232     '\u2028': 'u2028',
233     '\u2029': 'u2029'
234   };
235
236   /*--------------------------------------------------------------------------*/
237
238   /**
239    * Creates a `lodash` object, that wraps the given `value`, to enable method
240    * chaining.
241    *
242    * In addition to Lo-Dash methods, wrappers also have the following `Array` methods:
243    * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`,
244    * and `unshift`
245    *
246    * The chainable wrapper functions are:
247    * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`, `compose`,
248    * `concat`, `countBy`, `debounce`, `defaults`, `defer`, `delay`, `difference`,
249    * `filter`, `flatten`, `forEach`, `forIn`, `forOwn`, `functions`, `groupBy`,
250    * `initial`, `intersection`, `invert`, `invoke`, `keys`, `map`, `max`, `memoize`,
251    * `merge`, `min`, `object`, `omit`, `once`, `pairs`, `partial`, `partialRight`,
252    * `pick`, `pluck`, `push`, `range`, `reject`, `rest`, `reverse`, `shuffle`,
253    * `slice`, `sort`, `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`,
254    * `union`, `uniq`, `unshift`, `values`, `where`, `without`, `wrap`, and `zip`
255    *
256    * The non-chainable wrapper functions are:
257    * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `has`, `identity`,
258    * `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`, `isEmpty`,
259    * `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`, `isObject`,
260    * `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`, `lastIndexOf`,
261    * `mixin`, `noConflict`, `pop`, `random`, `reduce`, `reduceRight`, `result`,
262    * `shift`, `size`, `some`, `sortedIndex`, `template`, `unescape`, and `uniqueId`
263    *
264    * The wrapper functions `first` and `last` return wrapped values when `n` is
265    * passed, otherwise they return unwrapped values.
266    *
267    * @name _
268    * @constructor
269    * @category Chaining
270    * @param {Mixed} value The value to wrap in a `lodash` instance.
271    * @returns {Object} Returns a `lodash` instance.
272    */
273   function lodash(value) {
274     // exit early if already wrapped, even if wrapped by a different `lodash` constructor
275     if (value && typeof value == 'object' && value.__wrapped__) {
276       return value;
277     }
278     // allow invoking `lodash` without the `new` operator
279     if (!(this instanceof lodash)) {
280       return new lodash(value);
281     }
282     this.__wrapped__ = value;
283   }
284
285   /**
286    * By default, the template delimiters used by Lo-Dash are similar to those in
287    * embedded Ruby (ERB). Change the following template settings to use alternative
288    * delimiters.
289    *
290    * @static
291    * @memberOf _
292    * @type Object
293    */
294   lodash.templateSettings = {
295
296     /**
297      * Used to detect `data` property values to be HTML-escaped.
298      *
299      * @memberOf _.templateSettings
300      * @type RegExp
301      */
302     'escape': /<%-([\s\S]+?)%>/g,
303
304     /**
305      * Used to detect code to be evaluated.
306      *
307      * @memberOf _.templateSettings
308      * @type RegExp
309      */
310     'evaluate': /<%([\s\S]+?)%>/g,
311
312     /**
313      * Used to detect `data` property values to inject.
314      *
315      * @memberOf _.templateSettings
316      * @type RegExp
317      */
318     'interpolate': reInterpolate,
319
320     /**
321      * Used to reference the data object in the template text.
322      *
323      * @memberOf _.templateSettings
324      * @type String
325      */
326     'variable': '',
327
328     /**
329      * Used to import variables into the compiled template.
330      *
331      * @memberOf _.templateSettings
332      * @type Object
333      */
334     'imports': {
335
336       /**
337        * A reference to the `lodash` function.
338        *
339        * @memberOf _.templateSettings.imports
340        * @type Function
341        */
342       '_': lodash
343     }
344   };
345
346   /*--------------------------------------------------------------------------*/
347
348   /**
349    * The template used to create iterator functions.
350    *
351    * @private
352    * @param {Obect} data The data object used to populate the text.
353    * @returns {String} Returns the interpolated text.
354    */
355   var iteratorTemplate = function(obj) {
356     
357     var __p = 'var index, iterable = ' +
358     (obj.firstArg ) +
359     ', result = iterable;\nif (!iterable) return result;\n' +
360     (obj.top ) +
361     ';\n';
362      if (obj.arrays) {
363     __p += 'var length = iterable.length; index = -1;\nif (' +
364     (obj.arrays ) +
365     ') {  ';
366      if (obj.noCharByIndex) {
367     __p += '\n  if (isString(iterable)) {\n    iterable = iterable.split(\'\')\n  }  ';
368      } ;
369     __p += '\n  while (++index < length) {\n    ' +
370     (obj.loop ) +
371     '\n  }\n}\nelse {  ';
372       } else if (obj.nonEnumArgs) {
373     __p += '\n  var length = iterable.length; index = -1;\n  if (length && isArguments(iterable)) {\n    while (++index < length) {\n      index += \'\';\n      ' +
374     (obj.loop ) +
375     '\n    }\n  } else {  ';
376      } ;
377     
378      if (obj.hasEnumPrototype) {
379     __p += '\n  var skipProto = typeof iterable == \'function\';\n  ';
380      } ;
381     
382      if (obj.isKeysFast && obj.useHas) {
383     __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    ';
384      if (obj.hasEnumPrototype) {
385     __p += 'if (!(skipProto && index == \'prototype\')) {\n  ';
386      } ;
387     __p += 
388     (obj.loop ) +
389     '';
390      if (obj.hasEnumPrototype) {
391     __p += '}\n';
392      } ;
393     __p += '  }  ';
394      } else {
395     __p += '\n  for (index in iterable) {';
396         if (obj.hasEnumPrototype || obj.useHas) {
397     __p += '\n    if (';
398           if (obj.hasEnumPrototype) {
399     __p += '!(skipProto && index == \'prototype\')';
400      }      if (obj.hasEnumPrototype && obj.useHas) {
401     __p += ' && ';
402      }      if (obj.useHas) {
403     __p += 'hasOwnProperty.call(iterable, index)';
404      }    ;
405     __p += ') {    ';
406      } ;
407     __p += 
408     (obj.loop ) +
409     ';    ';
410      if (obj.hasEnumPrototype || obj.useHas) {
411     __p += '\n    }';
412      } ;
413     __p += '\n  }  ';
414      } ;
415     
416      if (obj.hasDontEnumBug) {
417     __p += '\n\n  var ctor = iterable.constructor;\n    ';
418      for (var k = 0; k < 7; k++) {
419     __p += '\n  index = \'' +
420     (obj.shadowed[k] ) +
421     '\';\n  if (';
422           if (obj.shadowed[k] == 'constructor') {
423     __p += '!(ctor && ctor.prototype === iterable) && ';
424           } ;
425     __p += 'hasOwnProperty.call(iterable, index)) {\n    ' +
426     (obj.loop ) +
427     '\n  }    ';
428      } ;
429     
430      } ;
431     
432      if (obj.arrays || obj.nonEnumArgs) {
433     __p += '\n}';
434      } ;
435     __p += 
436     (obj.bottom ) +
437     ';\nreturn result';
438     
439     
440     return __p
441   };
442
443   /** Reusable iterator options for `assign` and `defaults` */
444   var defaultsIteratorOptions = {
445     'args': 'object, source, guard',
446     'top':
447       'var args = arguments,\n' +
448       '    argsIndex = 0,\n' +
449       "    argsLength = typeof guard == 'number' ? 2 : args.length;\n" +
450       'while (++argsIndex < argsLength) {\n' +
451       '  iterable = args[argsIndex];\n' +
452       '  if (iterable && objectTypes[typeof iterable]) {',
453     'loop': "if (typeof result[index] == 'undefined') result[index] = iterable[index]",
454     'bottom': '  }\n}'
455   };
456
457   /** Reusable iterator options shared by `each`, `forIn`, and `forOwn` */
458   var eachIteratorOptions = {
459     'args': 'collection, callback, thisArg',
460     'top': "callback = callback && typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg)",
461     'arrays': "typeof length == 'number'",
462     'loop': 'if (callback(iterable[index], index, collection) === false) return result'
463   };
464
465   /** Reusable iterator options for `forIn` and `forOwn` */
466   var forOwnIteratorOptions = {
467     'top': 'if (!objectTypes[typeof iterable]) return result;\n' + eachIteratorOptions.top,
468     'arrays': false
469   };
470
471   /*--------------------------------------------------------------------------*/
472
473   /**
474    * Creates a function optimized to search large arrays for a given `value`,
475    * starting at `fromIndex`, using strict equality for comparisons, i.e. `===`.
476    *
477    * @private
478    * @param {Array} array The array to search.
479    * @param {Mixed} value The value to search for.
480    * @param {Number} [fromIndex=0] The index to search from.
481    * @param {Number} [largeSize=30] The length at which an array is considered large.
482    * @returns {Boolean} Returns `true`, if `value` is found, else `false`.
483    */
484   function cachedContains(array, fromIndex, largeSize) {
485     fromIndex || (fromIndex = 0);
486
487     var length = array.length,
488         isLarge = (length - fromIndex) >= (largeSize || largeArraySize);
489
490     if (isLarge) {
491       var cache = {},
492           index = fromIndex - 1;
493
494       while (++index < length) {
495         // manually coerce `value` to a string because `hasOwnProperty`, in some
496         // older versions of Firefox, coerces objects incorrectly
497         var key = array[index] + '';
498         (hasOwnProperty.call(cache, key) ? cache[key] : (cache[key] = [])).push(array[index]);
499       }
500     }
501     return function(value) {
502       if (isLarge) {
503         var key = value + '';
504         return hasOwnProperty.call(cache, key) && indexOf(cache[key], value) > -1;
505       }
506       return indexOf(array, value, fromIndex) > -1;
507     }
508   }
509
510   /**
511    * Used by `_.max` and `_.min` as the default `callback` when a given
512    * `collection` is a string value.
513    *
514    * @private
515    * @param {String} value The character to inspect.
516    * @returns {Number} Returns the code unit of given character.
517    */
518   function charAtCallback(value) {
519     return value.charCodeAt(0);
520   }
521
522   /**
523    * Used by `sortBy` to compare transformed `collection` values, stable sorting
524    * them in ascending order.
525    *
526    * @private
527    * @param {Object} a The object to compare to `b`.
528    * @param {Object} b The object to compare to `a`.
529    * @returns {Number} Returns the sort order indicator of `1` or `-1`.
530    */
531   function compareAscending(a, b) {
532     var ai = a.index,
533         bi = b.index;
534
535     a = a.criteria;
536     b = b.criteria;
537
538     // ensure a stable sort in V8 and other engines
539     // http://code.google.com/p/v8/issues/detail?id=90
540     if (a !== b) {
541       if (a > b || typeof a == 'undefined') {
542         return 1;
543       }
544       if (a < b || typeof b == 'undefined') {
545         return -1;
546       }
547     }
548     return ai < bi ? -1 : 1;
549   }
550
551   /**
552    * Creates a function that, when called, invokes `func` with the `this` binding
553    * of `thisArg` and prepends any `partialArgs` to the arguments passed to the
554    * bound function.
555    *
556    * @private
557    * @param {Function|String} func The function to bind or the method name.
558    * @param {Mixed} [thisArg] The `this` binding of `func`.
559    * @param {Array} partialArgs An array of arguments to be partially applied.
560    * @param {Object} [rightIndicator] Used to indicate partially applying arguments from the right.
561    * @returns {Function} Returns the new bound function.
562    */
563   function createBound(func, thisArg, partialArgs, rightIndicator) {
564     var isFunc = isFunction(func),
565         isPartial = !partialArgs,
566         key = thisArg;
567
568     // juggle arguments
569     if (isPartial) {
570       partialArgs = thisArg;
571     }
572     if (!isFunc) {
573       thisArg = func;
574     }
575
576     function bound() {
577       // `Function#bind` spec
578       // http://es5.github.com/#x15.3.4.5
579       var args = arguments,
580           thisBinding = isPartial ? this : thisArg;
581
582       if (!isFunc) {
583         func = thisArg[key];
584       }
585       if (partialArgs.length) {
586         args = args.length
587           ? (args = slice(args), rightIndicator ? args.concat(partialArgs) : partialArgs.concat(args))
588           : partialArgs;
589       }
590       if (this instanceof bound) {
591         // ensure `new bound` is an instance of `bound` and `func`
592         noop.prototype = func.prototype;
593         thisBinding = new noop;
594         noop.prototype = null;
595
596         // mimic the constructor's `return` behavior
597         // http://es5.github.com/#x13.2.2
598         var result = func.apply(thisBinding, args);
599         return isObject(result) ? result : thisBinding;
600       }
601       return func.apply(thisBinding, args);
602     }
603     return bound;
604   }
605
606   /**
607    * Produces a callback bound to an optional `thisArg`. If `func` is a property
608    * name, the created callback will return the property value for a given element.
609    * If `func` is an object, the created callback will return `true` for elements
610    * that contain the equivalent object properties, otherwise it will return `false`.
611    *
612    * @private
613    * @param {Mixed} [func=identity] The value to convert to a callback.
614    * @param {Mixed} [thisArg] The `this` binding of the created callback.
615    * @param {Number} [argCount=3] The number of arguments the callback accepts.
616    * @returns {Function} Returns a callback function.
617    */
618   function createCallback(func, thisArg, argCount) {
619     if (func == null) {
620       return identity;
621     }
622     var type = typeof func;
623     if (type != 'function') {
624       if (type != 'object') {
625         return function(object) {
626           return object[func];
627         };
628       }
629       var props = keys(func);
630       return function(object) {
631         var length = props.length,
632             result = false;
633         while (length--) {
634           if (!(result = isEqual(object[props[length]], func[props[length]], indicatorObject))) {
635             break;
636           }
637         }
638         return result;
639       };
640     }
641     if (typeof thisArg != 'undefined') {
642       if (argCount === 1) {
643         return function(value) {
644           return func.call(thisArg, value);
645         };
646       }
647       if (argCount === 2) {
648         return function(a, b) {
649           return func.call(thisArg, a, b);
650         };
651       }
652       if (argCount === 4) {
653         return function(accumulator, value, index, object) {
654           return func.call(thisArg, accumulator, value, index, object);
655         };
656       }
657       return function(value, index, object) {
658         return func.call(thisArg, value, index, object);
659       };
660     }
661     return func;
662   }
663
664   /**
665    * Creates compiled iteration functions.
666    *
667    * @private
668    * @param {Object} [options1, options2, ...] The compile options object(s).
669    *  arrays - A string of code to determine if the iterable is an array or array-like.
670    *  useHas - A boolean to specify using `hasOwnProperty` checks in the object loop.
671    *  args - A string of comma separated arguments the iteration function will accept.
672    *  top - A string of code to execute before the iteration branches.
673    *  loop - A string of code to execute in the object loop.
674    *  bottom - A string of code to execute after the iteration branches.
675    *
676    * @returns {Function} Returns the compiled function.
677    */
678   function createIterator() {
679     var data = {
680       // support properties
681       'hasDontEnumBug': hasDontEnumBug,
682       'hasEnumPrototype': hasEnumPrototype,
683       'isKeysFast': isKeysFast,
684       'nonEnumArgs': nonEnumArgs,
685       'noCharByIndex': noCharByIndex,
686       'shadowed': shadowed,
687
688       // iterator options
689       'arrays': 'isArray(iterable)',
690       'bottom': '',
691       'loop': '',
692       'top': '',
693       'useHas': true
694     };
695
696     // merge options into a template data object
697     for (var object, index = 0; object = arguments[index]; index++) {
698       for (var key in object) {
699         data[key] = object[key];
700       }
701     }
702     var args = data.args;
703     data.firstArg = /^[^,]+/.exec(args)[0];
704
705     // create the function factory
706     var factory = Function(
707         'createCallback, hasOwnProperty, isArguments, isArray, isString, ' +
708         'objectTypes, nativeKeys',
709       'return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}'
710     );
711     // return the compiled function
712     return factory(
713       createCallback, hasOwnProperty, isArguments, isArray, isString,
714       objectTypes, nativeKeys
715     );
716   }
717
718   /**
719    * A function compiled to iterate `arguments` objects, arrays, objects, and
720    * strings consistenly across environments, executing the `callback` for each
721    * element in the `collection`. The `callback` is bound to `thisArg` and invoked
722    * with three arguments; (value, index|key, collection). Callbacks may exit
723    * iteration early by explicitly returning `false`.
724    *
725    * @private
726    * @type Function
727    * @param {Array|Object|String} collection The collection to iterate over.
728    * @param {Function} [callback=identity] The function called per iteration.
729    * @param {Mixed} [thisArg] The `this` binding of `callback`.
730    * @returns {Array|Object|String} Returns `collection`.
731    */
732   var each = createIterator(eachIteratorOptions);
733
734   /**
735    * Used by `template` to escape characters for inclusion in compiled
736    * string literals.
737    *
738    * @private
739    * @param {String} match The matched character to escape.
740    * @returns {String} Returns the escaped character.
741    */
742   function escapeStringChar(match) {
743     return '\\' + stringEscapes[match];
744   }
745
746   /**
747    * Used by `escape` to convert characters to HTML entities.
748    *
749    * @private
750    * @param {String} match The matched character to escape.
751    * @returns {String} Returns the escaped character.
752    */
753   function escapeHtmlChar(match) {
754     return htmlEscapes[match];
755   }
756
757   /**
758    * Checks if `value` is a DOM node in IE < 9.
759    *
760    * @private
761    * @param {Mixed} value The value to check.
762    * @returns {Boolean} Returns `true` if the `value` is a DOM node, else `false`.
763    */
764   function isNode(value) {
765     // IE < 9 presents DOM nodes as `Object` objects except they have `toString`
766     // methods that are `typeof` "string" and still can coerce nodes to strings
767     return typeof value.toString != 'function' && typeof (value + '') == 'string';
768   }
769
770   /**
771    * A no-operation function.
772    *
773    * @private
774    */
775   function noop() {
776     // no operation performed
777   }
778
779   /**
780    * Slices the `collection` from the `start` index up to, but not including,
781    * the `end` index.
782    *
783    * Note: This function is used, instead of `Array#slice`, to support node lists
784    * in IE < 9 and to ensure dense arrays are returned.
785    *
786    * @private
787    * @param {Array|Object|String} collection The collection to slice.
788    * @param {Number} start The start index.
789    * @param {Number} end The end index.
790    * @returns {Array} Returns the new array.
791    */
792   function slice(array, start, end) {
793     start || (start = 0);
794     if (typeof end == 'undefined') {
795       end = array ? array.length : 0;
796     }
797     var index = -1,
798         length = end - start || 0,
799         result = Array(length < 0 ? 0 : length);
800
801     while (++index < length) {
802       result[index] = array[start + index];
803     }
804     return result;
805   }
806
807   /**
808    * Used by `unescape` to convert HTML entities to characters.
809    *
810    * @private
811    * @param {String} match The matched character to unescape.
812    * @returns {String} Returns the unescaped character.
813    */
814   function unescapeHtmlChar(match) {
815     return htmlUnescapes[match];
816   }
817
818   /*--------------------------------------------------------------------------*/
819
820   /**
821    * Checks if `value` is an `arguments` object.
822    *
823    * @static
824    * @memberOf _
825    * @category Objects
826    * @param {Mixed} value The value to check.
827    * @returns {Boolean} Returns `true`, if the `value` is an `arguments` object, else `false`.
828    * @example
829    *
830    * (function() { return _.isArguments(arguments); })(1, 2, 3);
831    * // => true
832    *
833    * _.isArguments([1, 2, 3]);
834    * // => false
835    */
836   function isArguments(value) {
837     return toString.call(value) == argsClass;
838   }
839   // fallback for browsers that can't detect `arguments` objects by [[Class]]
840   if (noArgsClass) {
841     isArguments = function(value) {
842       return value ? hasOwnProperty.call(value, 'callee') : false;
843     };
844   }
845
846   /**
847    * Iterates over `object`'s own and inherited enumerable properties, executing
848    * the `callback` for each property. The `callback` is bound to `thisArg` and
849    * invoked with three arguments; (value, key, object). Callbacks may exit iteration
850    * early by explicitly returning `false`.
851    *
852    * @static
853    * @memberOf _
854    * @type Function
855    * @category Objects
856    * @param {Object} object The object to iterate over.
857    * @param {Function} [callback=identity] The function called per iteration.
858    * @param {Mixed} [thisArg] The `this` binding of `callback`.
859    * @returns {Object} Returns `object`.
860    * @example
861    *
862    * function Dog(name) {
863    *   this.name = name;
864    * }
865    *
866    * Dog.prototype.bark = function() {
867    *   alert('Woof, woof!');
868    * };
869    *
870    * _.forIn(new Dog('Dagny'), function(value, key) {
871    *   alert(key);
872    * });
873    * // => alerts 'name' and 'bark' (order is not guaranteed)
874    */
875   var forIn = createIterator(eachIteratorOptions, forOwnIteratorOptions, {
876     'useHas': false
877   });
878
879   /**
880    * Iterates over an object's own enumerable properties, executing the `callback`
881    * for each property. The `callback` is bound to `thisArg` and invoked with three
882    * arguments; (value, key, object). Callbacks may exit iteration early by explicitly
883    * returning `false`.
884    *
885    * @static
886    * @memberOf _
887    * @type Function
888    * @category Objects
889    * @param {Object} object The object to iterate over.
890    * @param {Function} [callback=identity] The function called per iteration.
891    * @param {Mixed} [thisArg] The `this` binding of `callback`.
892    * @returns {Object} Returns `object`.
893    * @example
894    *
895    * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
896    *   alert(key);
897    * });
898    * // => alerts '0', '1', and 'length' (order is not guaranteed)
899    */
900   var forOwn = createIterator(eachIteratorOptions, forOwnIteratorOptions);
901
902   /**
903    * Checks if `value` is an array.
904    *
905    * @static
906    * @memberOf _
907    * @category Objects
908    * @param {Mixed} value The value to check.
909    * @returns {Boolean} Returns `true`, if the `value` is an array, else `false`.
910    * @example
911    *
912    * (function() { return _.isArray(arguments); })();
913    * // => false
914    *
915    * _.isArray([1, 2, 3]);
916    * // => true
917    */
918   var isArray = nativeIsArray || function(value) {
919     // `instanceof` may cause a memory leak in IE 7 if `value` is a host object
920     // http://ajaxian.com/archives/working-aroung-the-instanceof-memory-leak
921     return (argsAreObjects && value instanceof Array) || toString.call(value) == arrayClass;
922   };
923
924   /**
925    * Creates an array composed of the own enumerable property names of `object`.
926    *
927    * @static
928    * @memberOf _
929    * @category Objects
930    * @param {Object} object The object to inspect.
931    * @returns {Array} Returns a new array of property names.
932    * @example
933    *
934    * _.keys({ 'one': 1, 'two': 2, 'three': 3 });
935    * // => ['one', 'two', 'three'] (order is not guaranteed)
936    */
937   var keys = !nativeKeys ? shimKeys : function(object) {
938     if (!isObject(object)) {
939       return [];
940     }
941     if ((hasEnumPrototype && typeof object == 'function') ||
942         (nonEnumArgs && object.length && isArguments(object))) {
943       return shimKeys(object);
944     }
945     return nativeKeys(object);
946   };
947
948   /**
949    * A fallback implementation of `isPlainObject` that checks if a given `value`
950    * is an object created by the `Object` constructor, assuming objects created
951    * by the `Object` constructor have no inherited enumerable properties and that
952    * there are no `Object.prototype` extensions.
953    *
954    * @private
955    * @param {Mixed} value The value to check.
956    * @returns {Boolean} Returns `true`, if `value` is a plain object, else `false`.
957    */
958   function shimIsPlainObject(value) {
959     // avoid non-objects and false positives for `arguments` objects
960     var result = false;
961     if (!(value && typeof value == 'object') || isArguments(value)) {
962       return result;
963     }
964     // check that the constructor is `Object` (i.e. `Object instanceof Object`)
965     var ctor = value.constructor;
966     if ((!isFunction(ctor) && (!noNodeClass || !isNode(value))) || ctor instanceof ctor) {
967       // IE < 9 iterates inherited properties before own properties. If the first
968       // iterated property is an object's own property then there are no inherited
969       // enumerable properties.
970       if (iteratesOwnLast) {
971         forIn(value, function(value, key, object) {
972           result = !hasOwnProperty.call(object, key);
973           return false;
974         });
975         return result === false;
976       }
977       // In most environments an object's own properties are iterated before
978       // its inherited properties. If the last iterated property is an object's
979       // own property then there are no inherited enumerable properties.
980       forIn(value, function(value, key) {
981         result = key;
982       });
983       return result === false || hasOwnProperty.call(value, result);
984     }
985     return result;
986   }
987
988   /**
989    * A fallback implementation of `Object.keys` that produces an array of the
990    * given object's own enumerable property names.
991    *
992    * @private
993    * @param {Object} object The object to inspect.
994    * @returns {Array} Returns a new array of property names.
995    */
996   function shimKeys(object) {
997     var result = [];
998     forOwn(object, function(value, key) {
999       result.push(key);
1000     });
1001     return result;
1002   }
1003
1004   /**
1005    * Used to convert characters to HTML entities:
1006    *
1007    * Though the `>` character is escaped for symmetry, characters like `>` and `/`
1008    * don't require escaping in HTML and have no special meaning unless they're part
1009    * of a tag or an unquoted attribute value.
1010    * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact")
1011    */
1012   var htmlEscapes = {
1013     '&': '&amp;',
1014     '<': '&lt;',
1015     '>': '&gt;',
1016     '"': '&quot;',
1017     "'": '&#39;'
1018   };
1019
1020   /** Used to convert HTML entities to characters */
1021   var htmlUnescapes = invert(htmlEscapes);
1022
1023   /*--------------------------------------------------------------------------*/
1024
1025   /**
1026    * Assigns own enumerable properties of source object(s) to the destination
1027    * object. Subsequent sources will overwrite propery assignments of previous
1028    * sources. If a `callback` function is passed, it will be executed to produce
1029    * the assigned values. The `callback` is bound to `thisArg` and invoked with
1030    * two arguments; (objectValue, sourceValue).
1031    *
1032    * @static
1033    * @memberOf _
1034    * @type Function
1035    * @alias extend
1036    * @category Objects
1037    * @param {Object} object The destination object.
1038    * @param {Object} [source1, source2, ...] The source objects.
1039    * @param {Function} [callback] The function to customize assigning values.
1040    * @param {Mixed} [thisArg] The `this` binding of `callback`.
1041    * @returns {Object} Returns the destination object.
1042    * @example
1043    *
1044    * _.assign({ 'name': 'moe' }, { 'age': 40 });
1045    * // => { 'name': 'moe', 'age': 40 }
1046    *
1047    * var defaults = _.partialRight(_.assign, function(a, b) {
1048    *   return typeof a == 'undefined' ? b : a;
1049    * });
1050    *
1051    * var food = { 'name': 'apple' };
1052    * defaults(food, { 'name': 'banana', 'type': 'fruit' });
1053    * // => { 'name': 'apple', 'type': 'fruit' }
1054    */
1055   var assign = createIterator(defaultsIteratorOptions, {
1056     'top':
1057       defaultsIteratorOptions.top.replace(';',
1058         ';\n' +
1059         "if (argsLength > 3 && typeof args[argsLength - 2] == 'function') {\n" +
1060         '  var callback = createCallback(args[--argsLength - 1], args[argsLength--], 2);\n' +
1061         "} else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {\n" +
1062         '  callback = args[--argsLength];\n' +
1063         '}'
1064       ),
1065     'loop': 'result[index] = callback ? callback(result[index], iterable[index]) : iterable[index]'
1066   });
1067
1068   /**
1069    * Creates a clone of `value`. If `deep` is `true`, nested objects will also
1070    * be cloned, otherwise they will be assigned by reference. If a `callback`
1071    * function is passed, it will be executed to produce the cloned values. If
1072    * `callback` returns `undefined`, cloning will be handled by the method instead.
1073    * The `callback` is bound to `thisArg` and invoked with one argument; (value).
1074    *
1075    * @static
1076    * @memberOf _
1077    * @category Objects
1078    * @param {Mixed} value The value to clone.
1079    * @param {Boolean} [deep=false] A flag to indicate a deep clone.
1080    * @param {Function} [callback] The function to customize cloning values.
1081    * @param {Mixed} [thisArg] The `this` binding of `callback`.
1082    * @param- {Array} [stackA=[]] Internally used to track traversed source objects.
1083    * @param- {Array} [stackB=[]] Internally used to associate clones with source counterparts.
1084    * @returns {Mixed} Returns the cloned `value`.
1085    * @example
1086    *
1087    * var stooges = [
1088    *   { 'name': 'moe', 'age': 40 },
1089    *   { 'name': 'larry', 'age': 50 }
1090    * ];
1091    *
1092    * var shallow = _.clone(stooges);
1093    * shallow[0] === stooges[0];
1094    * // => true
1095    *
1096    * var deep = _.clone(stooges, true);
1097    * deep[0] === stooges[0];
1098    * // => false
1099    *
1100    * _.mixin({
1101    *   'clone': _.partialRight(_.clone, function(value) {
1102    *     return _.isElement(value) ? value.cloneNode(false) : undefined;
1103    *   })
1104    * });
1105    *
1106    * var clone = _.clone(document.body);
1107    * clone.childNodes.length;
1108    * // => 0
1109    */
1110   function clone(value, deep, callback, thisArg, stackA, stackB) {
1111     var result = value;
1112
1113     // allows working with "Collections" methods without using their `callback`
1114     // argument, `index|key`, for this method's `callback`
1115     if (typeof deep == 'function') {
1116       thisArg = callback;
1117       callback = deep;
1118       deep = false;
1119     }
1120     if (typeof callback == 'function') {
1121       callback = typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg, 1);
1122       result = callback(result);
1123
1124       var done = typeof result != 'undefined';
1125       if (!done) {
1126         result = value;
1127       }
1128     }
1129     // inspect [[Class]]
1130     var isObj = isObject(result);
1131     if (isObj) {
1132       var className = toString.call(result);
1133       if (!cloneableClasses[className] || (noNodeClass && isNode(result))) {
1134         return result;
1135       }
1136       var isArr = isArray(result);
1137     }
1138     // shallow clone
1139     if (!isObj || !deep) {
1140       return isObj && !done
1141         ? (isArr ? slice(result) : assign({}, result))
1142         : result;
1143     }
1144     var ctor = ctorByClass[className];
1145     switch (className) {
1146       case boolClass:
1147       case dateClass:
1148         return done ? result : new ctor(+result);
1149
1150       case numberClass:
1151       case stringClass:
1152         return done ? result : new ctor(result);
1153
1154       case regexpClass:
1155         return done ? result : ctor(result.source, reFlags.exec(result));
1156     }
1157     // check for circular references and return corresponding clone
1158     stackA || (stackA = []);
1159     stackB || (stackB = []);
1160
1161     var length = stackA.length;
1162     while (length--) {
1163       if (stackA[length] == value) {
1164         return stackB[length];
1165       }
1166     }
1167     // init cloned object
1168     if (!done) {
1169       result = isArr ? ctor(result.length) : {};
1170
1171       // add array properties assigned by `RegExp#exec`
1172       if (isArr) {
1173         if (hasOwnProperty.call(value, 'index')) {
1174           result.index = value.index;
1175         }
1176         if (hasOwnProperty.call(value, 'input')) {
1177           result.input = value.input;
1178         }
1179       }
1180     }
1181     // add the source value to the stack of traversed objects
1182     // and associate it with its clone
1183     stackA.push(value);
1184     stackB.push(result);
1185
1186     // recursively populate clone (susceptible to call stack limits)
1187     (isArr ? forEach : forOwn)(done ? result : value, function(objValue, key) {
1188       result[key] = clone(objValue, deep, callback, undefined, stackA, stackB);
1189     });
1190
1191     return result;
1192   }
1193
1194   /**
1195    * Creates a deep clone of `value`. If a `callback` function is passed, it will
1196    * be executed to produce the cloned values. If `callback` returns the value it
1197    * was passed, cloning will be handled by the method instead. The `callback` is
1198    * bound to `thisArg` and invoked with one argument; (value).
1199    *
1200    * Note: This function is loosely based on the structured clone algorithm. Functions
1201    * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and
1202    * objects created by constructors other than `Object` are cloned to plain `Object` objects.
1203    * See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm.
1204    *
1205    * @static
1206    * @memberOf _
1207    * @category Objects
1208    * @param {Mixed} value The value to deep clone.
1209    * @param {Function} [callback] The function to customize cloning values.
1210    * @param {Mixed} [thisArg] The `this` binding of `callback`.
1211    * @returns {Mixed} Returns the deep cloned `value`.
1212    * @example
1213    *
1214    * var stooges = [
1215    *   { 'name': 'moe', 'age': 40 },
1216    *   { 'name': 'larry', 'age': 50 }
1217    * ];
1218    *
1219    * var deep = _.cloneDeep(stooges);
1220    * deep[0] === stooges[0];
1221    * // => false
1222    *
1223    * var view = {
1224    *   'label': 'docs',
1225    *   'node': element
1226    * };
1227    *
1228    * var clone = _.cloneDeep(view, function(value) {
1229    *   return _.isElement(value) ? value.cloneNode(true) : value;
1230    * });
1231    *
1232    * clone.node == view.node;
1233    * // => false
1234    */
1235   function cloneDeep(value, callback, thisArg) {
1236     return clone(value, true, callback, thisArg);
1237   }
1238
1239   /**
1240    * Assigns own enumerable properties of source object(s) to the destination
1241    * object for all destination properties that resolve to `undefined`. Once a
1242    * property is set, additional defaults of the same property will be ignored.
1243    *
1244    * @static
1245    * @memberOf _
1246    * @type Function
1247    * @category Objects
1248    * @param {Object} object The destination object.
1249    * @param {Object} [source1, source2, ...] The source objects.
1250    * @param- {Object} [guard] Internally used to allow working with `_.reduce`
1251    *  without using its callback's `key` and `object` arguments as sources.
1252    * @returns {Object} Returns the destination object.
1253    * @example
1254    *
1255    * var food = { 'name': 'apple' };
1256    * _.defaults(food, { 'name': 'banana', 'type': 'fruit' });
1257    * // => { 'name': 'apple', 'type': 'fruit' }
1258    */
1259   var defaults = createIterator(defaultsIteratorOptions);
1260
1261   /**
1262    * Creates a sorted array of all enumerable properties, own and inherited,
1263    * of `object` that have function values.
1264    *
1265    * @static
1266    * @memberOf _
1267    * @alias methods
1268    * @category Objects
1269    * @param {Object} object The object to inspect.
1270    * @returns {Array} Returns a new array of property names that have function values.
1271    * @example
1272    *
1273    * _.functions(_);
1274    * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
1275    */
1276   function functions(object) {
1277     var result = [];
1278     forIn(object, function(value, key) {
1279       if (isFunction(value)) {
1280         result.push(key);
1281       }
1282     });
1283     return result.sort();
1284   }
1285
1286   /**
1287    * Checks if the specified object `property` exists and is a direct property,
1288    * instead of an inherited property.
1289    *
1290    * @static
1291    * @memberOf _
1292    * @category Objects
1293    * @param {Object} object The object to check.
1294    * @param {String} property The property to check for.
1295    * @returns {Boolean} Returns `true` if key is a direct property, else `false`.
1296    * @example
1297    *
1298    * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
1299    * // => true
1300    */
1301   function has(object, property) {
1302     return object ? hasOwnProperty.call(object, property) : false;
1303   }
1304
1305   /**
1306    * Creates an object composed of the inverted keys and values of the given `object`.
1307    *
1308    * @static
1309    * @memberOf _
1310    * @category Objects
1311    * @param {Object} object The object to invert.
1312    * @returns {Object} Returns the created inverted object.
1313    * @example
1314    *
1315    *  _.invert({ 'first': 'moe', 'second': 'larry' });
1316    * // => { 'moe': 'first', 'larry': 'second' } (order is not guaranteed)
1317    */
1318   function invert(object) {
1319     var index = -1,
1320         props = keys(object),
1321         length = props.length,
1322         result = {};
1323
1324     while (++index < length) {
1325       var key = props[index];
1326       result[object[key]] = key;
1327     }
1328     return result;
1329   }
1330
1331   /**
1332    * Checks if `value` is a boolean value.
1333    *
1334    * @static
1335    * @memberOf _
1336    * @category Objects
1337    * @param {Mixed} value The value to check.
1338    * @returns {Boolean} Returns `true`, if the `value` is a boolean value, else `false`.
1339    * @example
1340    *
1341    * _.isBoolean(null);
1342    * // => false
1343    */
1344   function isBoolean(value) {
1345     return value === true || value === false || toString.call(value) == boolClass;
1346   }
1347
1348   /**
1349    * Checks if `value` is a date.
1350    *
1351    * @static
1352    * @memberOf _
1353    * @category Objects
1354    * @param {Mixed} value The value to check.
1355    * @returns {Boolean} Returns `true`, if the `value` is a date, else `false`.
1356    * @example
1357    *
1358    * _.isDate(new Date);
1359    * // => true
1360    */
1361   function isDate(value) {
1362     return value instanceof Date || toString.call(value) == dateClass;
1363   }
1364
1365   /**
1366    * Checks if `value` is a DOM element.
1367    *
1368    * @static
1369    * @memberOf _
1370    * @category Objects
1371    * @param {Mixed} value The value to check.
1372    * @returns {Boolean} Returns `true`, if the `value` is a DOM element, else `false`.
1373    * @example
1374    *
1375    * _.isElement(document.body);
1376    * // => true
1377    */
1378   function isElement(value) {
1379     return value ? value.nodeType === 1 : false;
1380   }
1381
1382   /**
1383    * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a
1384    * length of `0` and objects with no own enumerable properties are considered
1385    * "empty".
1386    *
1387    * @static
1388    * @memberOf _
1389    * @category Objects
1390    * @param {Array|Object|String} value The value to inspect.
1391    * @returns {Boolean} Returns `true`, if the `value` is empty, else `false`.
1392    * @example
1393    *
1394    * _.isEmpty([1, 2, 3]);
1395    * // => false
1396    *
1397    * _.isEmpty({});
1398    * // => true
1399    *
1400    * _.isEmpty('');
1401    * // => true
1402    */
1403   function isEmpty(value) {
1404     var result = true;
1405     if (!value) {
1406       return result;
1407     }
1408     var className = toString.call(value),
1409         length = value.length;
1410
1411     if ((className == arrayClass || className == stringClass ||
1412         className == argsClass || (noArgsClass && isArguments(value))) ||
1413         (className == objectClass && typeof length == 'number' && isFunction(value.splice))) {
1414       return !length;
1415     }
1416     forOwn(value, function() {
1417       return (result = false);
1418     });
1419     return result;
1420   }
1421
1422   /**
1423    * Performs a deep comparison between two values to determine if they are
1424    * equivalent to each other. If `callback` is passed, it will be executed to
1425    * compare values. If `callback` returns `undefined`, comparisons will be handled
1426    * by the method instead. The `callback` is bound to `thisArg` and invoked with
1427    * two arguments; (a, b).
1428    *
1429    * @static
1430    * @memberOf _
1431    * @category Objects
1432    * @param {Mixed} a The value to compare.
1433    * @param {Mixed} b The other value to compare.
1434    * @param {Function} [callback] The function to customize comparing values.
1435    * @param {Mixed} [thisArg] The `this` binding of `callback`.
1436    * @param- {Object} [stackA=[]] Internally used track traversed `a` objects.
1437    * @param- {Object} [stackB=[]] Internally used track traversed `b` objects.
1438    * @returns {Boolean} Returns `true`, if the values are equvalent, else `false`.
1439    * @example
1440    *
1441    * var moe = { 'name': 'moe', 'age': 40 };
1442    * var copy = { 'name': 'moe', 'age': 40 };
1443    *
1444    * moe == copy;
1445    * // => false
1446    *
1447    * _.isEqual(moe, copy);
1448    * // => true
1449    *
1450    * var words = ['hello', 'goodbye'];
1451    * var otherWords = ['hi', 'goodbye'];
1452    *
1453    * _.isEqual(words, otherWords, function(a, b) {
1454    *   var reGreet = /^(?:hello|hi)$/i,
1455    *       aGreet = _.isString(a) && reGreet.test(a),
1456    *       bGreet = _.isString(b) && reGreet.test(b);
1457    *
1458    *   return (aGreet || bGreet) ? (aGreet == bGreet) : undefined;
1459    * });
1460    * // => true
1461    */
1462   function isEqual(a, b, callback, thisArg, stackA, stackB) {
1463     // used to indicate that when comparing objects, `a` has at least the properties of `b`
1464     var whereIndicator = callback === indicatorObject;
1465     if (callback && !whereIndicator) {
1466       callback = typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg, 2);
1467       var result = callback(a, b);
1468       if (typeof result != 'undefined') {
1469         return !!result;
1470       }
1471     }
1472     // exit early for identical values
1473     if (a === b) {
1474       // treat `+0` vs. `-0` as not equal
1475       return a !== 0 || (1 / a == 1 / b);
1476     }
1477     var type = typeof a,
1478         otherType = typeof b;
1479
1480     // exit early for unlike primitive values
1481     if (a === a &&
1482         (!a || (type != 'function' && type != 'object')) &&
1483         (!b || (otherType != 'function' && otherType != 'object'))) {
1484       return false;
1485     }
1486     // exit early for `null` and `undefined`, avoiding ES3's Function#call behavior
1487     // http://es5.github.com/#x15.3.4.4
1488     if (a == null || b == null) {
1489       return a === b;
1490     }
1491     // compare [[Class]] names
1492     var className = toString.call(a),
1493         otherClass = toString.call(b);
1494
1495     if (className == argsClass) {
1496       className = objectClass;
1497     }
1498     if (otherClass == argsClass) {
1499       otherClass = objectClass;
1500     }
1501     if (className != otherClass) {
1502       return false;
1503     }
1504     switch (className) {
1505       case boolClass:
1506       case dateClass:
1507         // coerce dates and booleans to numbers, dates to milliseconds and booleans
1508         // to `1` or `0`, treating invalid dates coerced to `NaN` as not equal
1509         return +a == +b;
1510
1511       case numberClass:
1512         // treat `NaN` vs. `NaN` as equal
1513         return a != +a
1514           ? b != +b
1515           // but treat `+0` vs. `-0` as not equal
1516           : (a == 0 ? (1 / a == 1 / b) : a == +b);
1517
1518       case regexpClass:
1519       case stringClass:
1520         // coerce regexes to strings (http://es5.github.com/#x15.10.6.4)
1521         // treat string primitives and their corresponding object instances as equal
1522         return a == b + '';
1523     }
1524     var isArr = className == arrayClass;
1525     if (!isArr) {
1526       // unwrap any `lodash` wrapped values
1527       if (a.__wrapped__ || b.__wrapped__) {
1528         return isEqual(a.__wrapped__ || a, b.__wrapped__ || b, callback, thisArg, stackA, stackB);
1529       }
1530       // exit for functions and DOM nodes
1531       if (className != objectClass || (noNodeClass && (isNode(a) || isNode(b)))) {
1532         return false;
1533       }
1534       // in older versions of Opera, `arguments` objects have `Array` constructors
1535       var ctorA = !argsAreObjects && isArguments(a) ? Object : a.constructor,
1536           ctorB = !argsAreObjects && isArguments(b) ? Object : b.constructor;
1537
1538       // non `Object` object instances with different constructors are not equal
1539       if (ctorA != ctorB && !(
1540             isFunction(ctorA) && ctorA instanceof ctorA &&
1541             isFunction(ctorB) && ctorB instanceof ctorB
1542           )) {
1543         return false;
1544       }
1545     }
1546     // assume cyclic structures are equal
1547     // the algorithm for detecting cyclic structures is adapted from ES 5.1
1548     // section 15.12.3, abstract operation `JO` (http://es5.github.com/#x15.12.3)
1549     stackA || (stackA = []);
1550     stackB || (stackB = []);
1551
1552     var length = stackA.length;
1553     while (length--) {
1554       if (stackA[length] == a) {
1555         return stackB[length] == b;
1556       }
1557     }
1558     var size = 0;
1559     result = true;
1560
1561     // add `a` and `b` to the stack of traversed objects
1562     stackA.push(a);
1563     stackB.push(b);
1564
1565     // recursively compare objects and arrays (susceptible to call stack limits)
1566     if (isArr) {
1567       length = a.length;
1568       size = b.length;
1569
1570       // compare lengths to determine if a deep comparison is necessary
1571       result = size == a.length;
1572       if (!result && !whereIndicator) {
1573         return result;
1574       }
1575       // deep compare the contents, ignoring non-numeric properties
1576       while (size--) {
1577         var index = length,
1578             value = b[size];
1579
1580         if (whereIndicator) {
1581           while (index--) {
1582             if ((result = isEqual(a[index], value, callback, thisArg, stackA, stackB))) {
1583               break;
1584             }
1585           }
1586         } else if (!(result = isEqual(a[size], value, callback, thisArg, stackA, stackB))) {
1587           break;
1588         }
1589       }
1590       return result;
1591     }
1592     // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys`
1593     // which, in this case, is more costly
1594     forIn(b, function(value, key, b) {
1595       if (hasOwnProperty.call(b, key)) {
1596         // count the number of properties.
1597         size++;
1598         // deep compare each property value.
1599         return (result = hasOwnProperty.call(a, key) && isEqual(a[key], value, callback, thisArg, stackA, stackB));
1600       }
1601     });
1602
1603     if (result && !whereIndicator) {
1604       // ensure both objects have the same number of properties
1605       forIn(a, function(value, key, a) {
1606         if (hasOwnProperty.call(a, key)) {
1607           // `size` will be `-1` if `a` has more properties than `b`
1608           return (result = --size > -1);
1609         }
1610       });
1611     }
1612     return result;
1613   }
1614
1615   /**
1616    * Checks if `value` is, or can be coerced to, a finite number.
1617    *
1618    * Note: This is not the same as native `isFinite`, which will return true for
1619    * booleans and empty strings. See http://es5.github.com/#x15.1.2.5.
1620    *
1621    * @static
1622    * @memberOf _
1623    * @category Objects
1624    * @param {Mixed} value The value to check.
1625    * @returns {Boolean} Returns `true`, if the `value` is finite, else `false`.
1626    * @example
1627    *
1628    * _.isFinite(-101);
1629    * // => true
1630    *
1631    * _.isFinite('10');
1632    * // => true
1633    *
1634    * _.isFinite(true);
1635    * // => false
1636    *
1637    * _.isFinite('');
1638    * // => false
1639    *
1640    * _.isFinite(Infinity);
1641    * // => false
1642    */
1643   function isFinite(value) {
1644     return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value));
1645   }
1646
1647   /**
1648    * Checks if `value` is a function.
1649    *
1650    * @static
1651    * @memberOf _
1652    * @category Objects
1653    * @param {Mixed} value The value to check.
1654    * @returns {Boolean} Returns `true`, if the `value` is a function, else `false`.
1655    * @example
1656    *
1657    * _.isFunction(_);
1658    * // => true
1659    */
1660   function isFunction(value) {
1661     return typeof value == 'function';
1662   }
1663   // fallback for older versions of Chrome and Safari
1664   if (isFunction(/x/)) {
1665     isFunction = function(value) {
1666       return value instanceof Function || toString.call(value) == funcClass;
1667     };
1668   }
1669
1670   /**
1671    * Checks if `value` is the language type of Object.
1672    * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
1673    *
1674    * @static
1675    * @memberOf _
1676    * @category Objects
1677    * @param {Mixed} value The value to check.
1678    * @returns {Boolean} Returns `true`, if the `value` is an object, else `false`.
1679    * @example
1680    *
1681    * _.isObject({});
1682    * // => true
1683    *
1684    * _.isObject([1, 2, 3]);
1685    * // => true
1686    *
1687    * _.isObject(1);
1688    * // => false
1689    */
1690   function isObject(value) {
1691     // check if the value is the ECMAScript language type of Object
1692     // http://es5.github.com/#x8
1693     // and avoid a V8 bug
1694     // http://code.google.com/p/v8/issues/detail?id=2291
1695     return value ? objectTypes[typeof value] : false;
1696   }
1697
1698   /**
1699    * Checks if `value` is `NaN`.
1700    *
1701    * Note: This is not the same as native `isNaN`, which will return `true` for
1702    * `undefined` and other values. See http://es5.github.com/#x15.1.2.4.
1703    *
1704    * @static
1705    * @memberOf _
1706    * @category Objects
1707    * @param {Mixed} value The value to check.
1708    * @returns {Boolean} Returns `true`, if the `value` is `NaN`, else `false`.
1709    * @example
1710    *
1711    * _.isNaN(NaN);
1712    * // => true
1713    *
1714    * _.isNaN(new Number(NaN));
1715    * // => true
1716    *
1717    * isNaN(undefined);
1718    * // => true
1719    *
1720    * _.isNaN(undefined);
1721    * // => false
1722    */
1723   function isNaN(value) {
1724     // `NaN` as a primitive is the only value that is not equal to itself
1725     // (perform the [[Class]] check first to avoid errors with some host objects in IE)
1726     return isNumber(value) && value != +value
1727   }
1728
1729   /**
1730    * Checks if `value` is `null`.
1731    *
1732    * @static
1733    * @memberOf _
1734    * @category Objects
1735    * @param {Mixed} value The value to check.
1736    * @returns {Boolean} Returns `true`, if the `value` is `null`, else `false`.
1737    * @example
1738    *
1739    * _.isNull(null);
1740    * // => true
1741    *
1742    * _.isNull(undefined);
1743    * // => false
1744    */
1745   function isNull(value) {
1746     return value === null;
1747   }
1748
1749   /**
1750    * Checks if `value` is a number.
1751    *
1752    * @static
1753    * @memberOf _
1754    * @category Objects
1755    * @param {Mixed} value The value to check.
1756    * @returns {Boolean} Returns `true`, if the `value` is a number, else `false`.
1757    * @example
1758    *
1759    * _.isNumber(8.4 * 5);
1760    * // => true
1761    */
1762   function isNumber(value) {
1763     return typeof value == 'number' || toString.call(value) == numberClass;
1764   }
1765
1766   /**
1767    * Checks if a given `value` is an object created by the `Object` constructor.
1768    *
1769    * @static
1770    * @memberOf _
1771    * @category Objects
1772    * @param {Mixed} value The value to check.
1773    * @returns {Boolean} Returns `true`, if `value` is a plain object, else `false`.
1774    * @example
1775    *
1776    * function Stooge(name, age) {
1777    *   this.name = name;
1778    *   this.age = age;
1779    * }
1780    *
1781    * _.isPlainObject(new Stooge('moe', 40));
1782    * // => false
1783    *
1784    * _.isPlainObject([1, 2, 3]);
1785    * // => false
1786    *
1787    * _.isPlainObject({ 'name': 'moe', 'age': 40 });
1788    * // => true
1789    */
1790   var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) {
1791     if (!(value && typeof value == 'object')) {
1792       return false;
1793     }
1794     var valueOf = value.valueOf,
1795         objProto = typeof valueOf == 'function' && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto);
1796
1797     return objProto
1798       ? value == objProto || (getPrototypeOf(value) == objProto && !isArguments(value))
1799       : shimIsPlainObject(value);
1800   };
1801
1802   /**
1803    * Checks if `value` is a regular expression.
1804    *
1805    * @static
1806    * @memberOf _
1807    * @category Objects
1808    * @param {Mixed} value The value to check.
1809    * @returns {Boolean} Returns `true`, if the `value` is a regular expression, else `false`.
1810    * @example
1811    *
1812    * _.isRegExp(/moe/);
1813    * // => true
1814    */
1815   function isRegExp(value) {
1816     return value instanceof RegExp || toString.call(value) == regexpClass;
1817   }
1818
1819   /**
1820    * Checks if `value` is a string.
1821    *
1822    * @static
1823    * @memberOf _
1824    * @category Objects
1825    * @param {Mixed} value The value to check.
1826    * @returns {Boolean} Returns `true`, if the `value` is a string, else `false`.
1827    * @example
1828    *
1829    * _.isString('moe');
1830    * // => true
1831    */
1832   function isString(value) {
1833     return typeof value == 'string' || toString.call(value) == stringClass;
1834   }
1835
1836   /**
1837    * Checks if `value` is `undefined`.
1838    *
1839    * @static
1840    * @memberOf _
1841    * @category Objects
1842    * @param {Mixed} value The value to check.
1843    * @returns {Boolean} Returns `true`, if the `value` is `undefined`, else `false`.
1844    * @example
1845    *
1846    * _.isUndefined(void 0);
1847    * // => true
1848    */
1849   function isUndefined(value) {
1850     return typeof value == 'undefined';
1851   }
1852
1853   /**
1854    * Recursively merges own enumerable properties of the source object(s), that
1855    * don't resolve to `undefined`, into the destination object. Subsequent sources
1856    * will overwrite propery assignments of previous sources. If a `callback` function
1857    * is passed, it will be executed to produce the merged values of the destination
1858    * and source properties. If `callback` returns `undefined`, merging will be
1859    * handled by the method instead. The `callback` is bound to `thisArg` and
1860    * invoked with two arguments; (objectValue, sourceValue).
1861    *
1862    * @static
1863    * @memberOf _
1864    * @category Objects
1865    * @param {Object} object The destination object.
1866    * @param {Object} [source1, source2, ...] The source objects.
1867    * @param {Function} [callback] The function to customize merging properties.
1868    * @param {Mixed} [thisArg] The `this` binding of `callback`.
1869    * @param- {Object} [deepIndicator] Internally used to indicate that `stackA`
1870    *  and `stackB` are arrays of traversed objects instead of source objects.
1871    * @param- {Array} [stackA=[]] Internally used to track traversed source objects.
1872    * @param- {Array} [stackB=[]] Internally used to associate values with their
1873    *  source counterparts.
1874    * @returns {Object} Returns the destination object.
1875    * @example
1876    *
1877    * var names = {
1878    *   'stooges': [
1879    *     { 'name': 'moe' },
1880    *     { 'name': 'larry' }
1881    *   ]
1882    * };
1883    *
1884    * var ages = {
1885    *   'stooges': [
1886    *     { 'age': 40 },
1887    *     { 'age': 50 }
1888    *   ]
1889    * };
1890    *
1891    * _.merge(names, ages);
1892    * // => { 'stooges': [{ 'name': 'moe', 'age': 40 }, { 'name': 'larry', 'age': 50 }] }
1893    *
1894    * var food = {
1895    *   'fruits': ['apple'],
1896    *   'vegetables': ['beet']
1897    * };
1898    *
1899    * var otherFood = {
1900    *   'fruits': ['banana'],
1901    *   'vegetables': ['carrot']
1902    * };
1903    *
1904    * _.merge(food, otherFood, function(a, b) {
1905    *   return _.isArray(a) ? a.concat(b) : undefined;
1906    * });
1907    * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] }
1908    */
1909   function merge(object, source, deepIndicator) {
1910     var args = arguments,
1911         index = 0,
1912         length = 2;
1913
1914     if (!isObject(object)) {
1915       return object;
1916     }
1917     if (deepIndicator === indicatorObject) {
1918       var callback = args[3],
1919           stackA = args[4],
1920           stackB = args[5];
1921     } else {
1922       stackA = [];
1923       stackB = [];
1924
1925       // allows working with `_.reduce` and `_.reduceRight` without
1926       // using their `callback` arguments, `index|key` and `collection`
1927       if (typeof deepIndicator != 'number') {
1928         length = args.length;
1929       }
1930       if (length > 3 && typeof args[length - 2] == 'function') {
1931         callback = createCallback(args[--length - 1], args[length--], 2);
1932       } else if (length > 2 && typeof args[length - 1] == 'function') {
1933         callback = args[--length];
1934       }
1935     }
1936     while (++index < length) {
1937       (isArray(args[index]) ? forEach : forOwn)(args[index], function(source, key) {
1938         var found,
1939             isArr,
1940             result = source,
1941             value = object[key];
1942
1943         if (source && ((isArr = isArray(source)) || isPlainObject(source))) {
1944           // avoid merging previously merged cyclic sources
1945           var stackLength = stackA.length;
1946           while (stackLength--) {
1947             if ((found = stackA[stackLength] == source)) {
1948               value = stackB[stackLength];
1949               break;
1950             }
1951           }
1952           if (!found) {
1953             value = isArr
1954               ? (isArray(value) ? value : [])
1955               : (isPlainObject(value) ? value : {});
1956
1957             if (callback) {
1958               result = callback(value, source);
1959               if (typeof result != 'undefined') {
1960                 value = result;
1961               }
1962             }
1963             // add `source` and associated `value` to the stack of traversed objects
1964             stackA.push(source);
1965             stackB.push(value);
1966
1967             // recursively merge objects and arrays (susceptible to call stack limits)
1968             if (!callback) {
1969               value = merge(value, source, indicatorObject, callback, stackA, stackB);
1970             }
1971           }
1972         }
1973         else {
1974           if (callback) {
1975             result = callback(value, source);
1976             if (typeof result == 'undefined') {
1977               result = source;
1978             }
1979           }
1980           if (typeof result != 'undefined') {
1981             value = result;
1982           }
1983         }
1984         object[key] = value;
1985       });
1986     }
1987     return object;
1988   }
1989
1990   /**
1991    * Creates a shallow clone of `object` excluding the specified properties.
1992    * Property names may be specified as individual arguments or as arrays of
1993    * property names. If a `callback` function is passed, it will be executed
1994    * for each property in the `object`, omitting the properties `callback`
1995    * returns truthy for. The `callback` is bound to `thisArg` and invoked
1996    * with three arguments; (value, key, object).
1997    *
1998    * @static
1999    * @memberOf _
2000    * @category Objects
2001    * @param {Object} object The source object.
2002    * @param {Function|String} callback|[prop1, prop2, ...] The properties to omit
2003    *  or the function called per iteration.
2004    * @param {Mixed} [thisArg] The `this` binding of `callback`.
2005    * @returns {Object} Returns an object without the omitted properties.
2006    * @example
2007    *
2008    * _.omit({ 'name': 'moe', 'age': 40 }, 'age');
2009    * // => { 'name': 'moe' }
2010    *
2011    * _.omit({ 'name': 'moe', 'age': 40 }, function(value) {
2012    *   return typeof value == 'number';
2013    * });
2014    * // => { 'name': 'moe' }
2015    */
2016   function omit(object, callback, thisArg) {
2017     var isFunc = typeof callback == 'function',
2018         result = {};
2019
2020     if (isFunc) {
2021       callback = createCallback(callback, thisArg);
2022     } else {
2023       var props = concat.apply(arrayRef, arguments);
2024     }
2025     forIn(object, function(value, key, object) {
2026       if (isFunc
2027             ? !callback(value, key, object)
2028             : indexOf(props, key, 1) < 0
2029           ) {
2030         result[key] = value;
2031       }
2032     });
2033     return result;
2034   }
2035
2036   /**
2037    * Creates a two dimensional array of the given object's key-value pairs,
2038    * i.e. `[[key1, value1], [key2, value2]]`.
2039    *
2040    * @static
2041    * @memberOf _
2042    * @category Objects
2043    * @param {Object} object The object to inspect.
2044    * @returns {Array} Returns new array of key-value pairs.
2045    * @example
2046    *
2047    * _.pairs({ 'moe': 30, 'larry': 40 });
2048    * // => [['moe', 30], ['larry', 40]] (order is not guaranteed)
2049    */
2050   function pairs(object) {
2051     var index = -1,
2052         props = keys(object),
2053         length = props.length,
2054         result = Array(length);
2055
2056     while (++index < length) {
2057       var key = props[index];
2058       result[index] = [key, object[key]];
2059     }
2060     return result;
2061   }
2062
2063   /**
2064    * Creates a shallow clone of `object` composed of the specified properties.
2065    * Property names may be specified as individual arguments or as arrays of property
2066    * names. If `callback` is passed, it will be executed for each property in the
2067    * `object`, picking the properties `callback` returns truthy for. The `callback`
2068    * is bound to `thisArg` and invoked with three arguments; (value, key, object).
2069    *
2070    * @static
2071    * @memberOf _
2072    * @category Objects
2073    * @param {Object} object The source object.
2074    * @param {Array|Function|String} callback|[prop1, prop2, ...] The function called
2075    *  per iteration or properties to pick, either as individual arguments or arrays.
2076    * @param {Mixed} [thisArg] The `this` binding of `callback`.
2077    * @returns {Object} Returns an object composed of the picked properties.
2078    * @example
2079    *
2080    * _.pick({ 'name': 'moe', '_userid': 'moe1' }, 'name');
2081    * // => { 'name': 'moe' }
2082    *
2083    * _.pick({ 'name': 'moe', '_userid': 'moe1' }, function(value, key) {
2084    *   return key.charAt(0) != '_';
2085    * });
2086    * // => { 'name': 'moe' }
2087    */
2088   function pick(object, callback, thisArg) {
2089     var result = {};
2090     if (typeof callback != 'function') {
2091       var index = 0,
2092           props = concat.apply(arrayRef, arguments),
2093           length = isObject(object) ? props.length : 0;
2094
2095       while (++index < length) {
2096         var key = props[index];
2097         if (key in object) {
2098           result[key] = object[key];
2099         }
2100       }
2101     } else {
2102       callback = createCallback(callback, thisArg);
2103       forIn(object, function(value, key, object) {
2104         if (callback(value, key, object)) {
2105           result[key] = value;
2106         }
2107       });
2108     }
2109     return result;
2110   }
2111
2112   /**
2113    * Creates an array composed of the own enumerable property values of `object`.
2114    *
2115    * @static
2116    * @memberOf _
2117    * @category Objects
2118    * @param {Object} object The object to inspect.
2119    * @returns {Array} Returns a new array of property values.
2120    * @example
2121    *
2122    * _.values({ 'one': 1, 'two': 2, 'three': 3 });
2123    * // => [1, 2, 3]
2124    */
2125   function values(object) {
2126     var index = -1,
2127         props = keys(object),
2128         length = props.length,
2129         result = Array(length);
2130
2131     while (++index < length) {
2132       result[index] = object[props[index]];
2133     }
2134     return result;
2135   }
2136
2137   /*--------------------------------------------------------------------------*/
2138
2139   /**
2140    * Creates an array of elements from the specified indexes, or keys, of the
2141    * `collection`. Indexes may be specified as individual arguments or as arrays
2142    * of indexes.
2143    *
2144    * @static
2145    * @memberOf _
2146    * @category Collections
2147    * @param {Array|Object|String} collection The collection to iterate over.
2148    * @param {Array|Number|String} [index1, index2, ...] The indexes of
2149    *  `collection` to retrieve, either as individual arguments or arrays.
2150    * @returns {Array} Returns a new array of elements corresponding to the
2151    *  provided indexes.
2152    * @example
2153    *
2154    * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]);
2155    * // => ['a', 'c', 'e']
2156    *
2157    * _.at(['moe', 'larry', 'curly'], 0, 2);
2158    * // => ['moe', 'curly']
2159    */
2160   function at(collection) {
2161     var index = -1,
2162         props = concat.apply(arrayRef, slice(arguments, 1)),
2163         length = props.length,
2164         result = Array(length);
2165
2166     if (noCharByIndex && isString(collection)) {
2167       collection = collection.split('');
2168     }
2169     while(++index < length) {
2170       result[index] = collection[props[index]];
2171     }
2172     return result;
2173   }
2174
2175   /**
2176    * Checks if a given `target` element is present in a `collection` using strict
2177    * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
2178    * as the offset from the end of the collection.
2179    *
2180    * @static
2181    * @memberOf _
2182    * @alias include
2183    * @category Collections
2184    * @param {Array|Object|String} collection The collection to iterate over.
2185    * @param {Mixed} target The value to check for.
2186    * @param {Number} [fromIndex=0] The index to search from.
2187    * @returns {Boolean} Returns `true` if the `target` element is found, else `false`.
2188    * @example
2189    *
2190    * _.contains([1, 2, 3], 1);
2191    * // => true
2192    *
2193    * _.contains([1, 2, 3], 1, 2);
2194    * // => false
2195    *
2196    * _.contains({ 'name': 'moe', 'age': 40 }, 'moe');
2197    * // => true
2198    *
2199    * _.contains('curly', 'ur');
2200    * // => true
2201    */
2202   function contains(collection, target, fromIndex) {
2203     var index = -1,
2204         length = collection ? collection.length : 0,
2205         result = false;
2206
2207     fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0;
2208     if (typeof length == 'number') {
2209       result = (isString(collection)
2210         ? collection.indexOf(target, fromIndex)
2211         : indexOf(collection, target, fromIndex)
2212       ) > -1;
2213     } else {
2214       each(collection, function(value) {
2215         if (++index >= fromIndex) {
2216           return !(result = value === target);
2217         }
2218       });
2219     }
2220     return result;
2221   }
2222
2223   /**
2224    * Creates an object composed of keys returned from running each element of the
2225    * `collection` through the given `callback`. The corresponding value of each key
2226    * is the number of times the key was returned by the `callback`. The `callback`
2227    * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
2228    *
2229    * If a property name is passed for `callback`, the created "_.pluck" style
2230    * callback will return the property value of the given element.
2231    *
2232    * If an object is passed for `callback`, the created "_.where" style callback
2233    * will return `true` for elements that have the propeties of the given object,
2234    * else `false`.
2235    *
2236    * @static
2237    * @memberOf _
2238    * @category Collections
2239    * @param {Array|Object|String} collection The collection to iterate over.
2240    * @param {Function|Object|String} [callback=identity] The function called per
2241    *  iteration. If a property name or object is passed, it will be used to create
2242    *  a "_.pluck" or "_.where" style callback, respectively.
2243    * @param {Mixed} [thisArg] The `this` binding of `callback`.
2244    * @returns {Object} Returns the composed aggregate object.
2245    * @example
2246    *
2247    * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); });
2248    * // => { '4': 1, '6': 2 }
2249    *
2250    * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
2251    * // => { '4': 1, '6': 2 }
2252    *
2253    * _.countBy(['one', 'two', 'three'], 'length');
2254    * // => { '3': 2, '5': 1 }
2255    */
2256   function countBy(collection, callback, thisArg) {
2257     var result = {};
2258     callback = createCallback(callback, thisArg);
2259
2260     forEach(collection, function(value, key, collection) {
2261       key = callback(value, key, collection) + '';
2262       (hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1);
2263     });
2264     return result;
2265   }
2266
2267   /**
2268    * Checks if the `callback` returns a truthy value for **all** elements of a
2269    * `collection`. The `callback` is bound to `thisArg` and invoked with three
2270    * arguments; (value, index|key, collection).
2271    *
2272    * If a property name is passed for `callback`, the created "_.pluck" style
2273    * callback will return the property value of the given element.
2274    *
2275    * If an object is passed for `callback`, the created "_.where" style callback
2276    * will return `true` for elements that have the propeties of the given object,
2277    * else `false`.
2278    *
2279    * @static
2280    * @memberOf _
2281    * @alias all
2282    * @category Collections
2283    * @param {Array|Object|String} collection The collection to iterate over.
2284    * @param {Function|Object|String} [callback=identity] The function called per
2285    *  iteration. If a property name or object is passed, it will be used to create
2286    *  a "_.pluck" or "_.where" style callback, respectively.
2287    * @param {Mixed} [thisArg] The `this` binding of `callback`.
2288    * @returns {Boolean} Returns `true` if all elements pass the callback check,
2289    *  else `false`.
2290    * @example
2291    *
2292    * _.every([true, 1, null, 'yes'], Boolean);
2293    * // => false
2294    *
2295    * var stooges = [
2296    *   { 'name': 'moe', 'age': 40 },
2297    *   { 'name': 'larry', 'age': 50 }
2298    * ];
2299    *
2300    * // using "_.pluck" callback shorthand
2301    * _.every(stooges, 'age');
2302    * // => true
2303    *
2304    * // using "_.where" callback shorthand
2305    * _.every(stooges, { 'age': 50 });
2306    * // => false
2307    */
2308   function every(collection, callback, thisArg) {
2309     var result = true;
2310     callback = createCallback(callback, thisArg);
2311
2312     if (isArray(collection)) {
2313       var index = -1,
2314           length = collection.length;
2315
2316       while (++index < length) {
2317         if (!(result = !!callback(collection[index], index, collection))) {
2318           break;
2319         }
2320       }
2321     } else {
2322       each(collection, function(value, index, collection) {
2323         return (result = !!callback(value, index, collection));
2324       });
2325     }
2326     return result;
2327   }
2328
2329   /**
2330    * Examines each element in a `collection`, returning an array of all elements
2331    * the `callback` returns truthy for. The `callback` is bound to `thisArg` and
2332    * invoked with three arguments; (value, index|key, collection).
2333    *
2334    * If a property name is passed for `callback`, the created "_.pluck" style
2335    * callback will return the property value of the given element.
2336    *
2337    * If an object is passed for `callback`, the created "_.where" style callback
2338    * will return `true` for elements that have the propeties of the given object,
2339    * else `false`.
2340    *
2341    * @static
2342    * @memberOf _
2343    * @alias select
2344    * @category Collections
2345    * @param {Array|Object|String} collection The collection to iterate over.
2346    * @param {Function|Object|String} [callback=identity] The function called per
2347    *  iteration. If a property name or object is passed, it will be used to create
2348    *  a "_.pluck" or "_.where" style callback, respectively.
2349    * @param {Mixed} [thisArg] The `this` binding of `callback`.
2350    * @returns {Array} Returns a new array of elements that passed the callback check.
2351    * @example
2352    *
2353    * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
2354    * // => [2, 4, 6]
2355    *
2356    * var food = [
2357    *   { 'name': 'apple',  'organic': false, 'type': 'fruit' },
2358    *   { 'name': 'carrot', 'organic': true,  'type': 'vegetable' }
2359    * ];
2360    *
2361    * // using "_.pluck" callback shorthand
2362    * _.filter(food, 'organic');
2363    * // => [{ 'name': 'carrot', 'organic': true, 'type': 'vegetable' }]
2364    *
2365    * // using "_.where" callback shorthand
2366    * _.filter(food, { 'type': 'fruit' });
2367    * // => [{ 'name': 'apple', 'organic': false, 'type': 'fruit' }]
2368    */
2369   function filter(collection, callback, thisArg) {
2370     var result = [];
2371     callback = createCallback(callback, thisArg);
2372
2373     if (isArray(collection)) {
2374       var index = -1,
2375           length = collection.length;
2376
2377       while (++index < length) {
2378         var value = collection[index];
2379         if (callback(value, index, collection)) {
2380           result.push(value);
2381         }
2382       }
2383     } else {
2384       each(collection, function(value, index, collection) {
2385         if (callback(value, index, collection)) {
2386           result.push(value);
2387         }
2388       });
2389     }
2390     return result;
2391   }
2392
2393   /**
2394    * Examines each element in a `collection`, returning the first that the `callback`
2395    * returns truthy for. The `callback` is bound to `thisArg` and invoked with three
2396    * arguments; (value, index|key, collection).
2397    *
2398    * If a property name is passed for `callback`, the created "_.pluck" style
2399    * callback will return the property value of the given element.
2400    *
2401    * If an object is passed for `callback`, the created "_.where" style callback
2402    * will return `true` for elements that have the propeties of the given object,
2403    * else `false`.
2404    *
2405    * @static
2406    * @memberOf _
2407    * @alias detect
2408    * @category Collections
2409    * @param {Array|Object|String} collection The collection to iterate over.
2410    * @param {Function|Object|String} [callback=identity] The function called per
2411    *  iteration. If a property name or object is passed, it will be used to create
2412    *  a "_.pluck" or "_.where" style callback, respectively.
2413    * @param {Mixed} [thisArg] The `this` binding of `callback`.
2414    * @returns {Mixed} Returns the element that passed the callback check,
2415    *  else `undefined`.
2416    * @example
2417    *
2418    * var even = _.find([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
2419    * // => 2
2420    *
2421    * var food = [
2422    *   { 'name': 'apple',  'organic': false, 'type': 'fruit' },
2423    *   { 'name': 'banana', 'organic': true,  'type': 'fruit' },
2424    *   { 'name': 'beet',   'organic': false, 'type': 'vegetable' },
2425    *   { 'name': 'carrot', 'organic': true,  'type': 'vegetable' }
2426    * ];
2427    *
2428    * // using "_.where" callback shorthand
2429    * var veggie = _.find(food, { 'type': 'vegetable' });
2430    * // => { 'name': 'beet', 'organic': false, 'type': 'vegetable' }
2431    *
2432    * // using "_.pluck" callback shorthand
2433    * var healthy = _.find(food, 'organic');
2434    * // => { 'name': 'banana', 'organic': true, 'type': 'fruit' }
2435    */
2436   function find(collection, callback, thisArg) {
2437     var result;
2438     callback = createCallback(callback, thisArg);
2439
2440     forEach(collection, function(value, index, collection) {
2441       if (callback(value, index, collection)) {
2442         result = value;
2443         return false;
2444       }
2445     });
2446     return result;
2447   }
2448
2449   /**
2450    * Iterates over a `collection`, executing the `callback` for each element in
2451    * the `collection`. The `callback` is bound to `thisArg` and invoked with three
2452    * arguments; (value, index|key, collection). Callbacks may exit iteration early
2453    * by explicitly returning `false`.
2454    *
2455    * @static
2456    * @memberOf _
2457    * @alias each
2458    * @category Collections
2459    * @param {Array|Object|String} collection The collection to iterate over.
2460    * @param {Function} [callback=identity] The function called per iteration.
2461    * @param {Mixed} [thisArg] The `this` binding of `callback`.
2462    * @returns {Array|Object|String} Returns `collection`.
2463    * @example
2464    *
2465    * _([1, 2, 3]).forEach(alert).join(',');
2466    * // => alerts each number and returns '1,2,3'
2467    *
2468    * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, alert);
2469    * // => alerts each number value (order is not guaranteed)
2470    */
2471   function forEach(collection, callback, thisArg) {
2472     if (callback && typeof thisArg == 'undefined' && isArray(collection)) {
2473       var index = -1,
2474           length = collection.length;
2475
2476       while (++index < length) {
2477         if (callback(collection[index], index, collection) === false) {
2478           break;
2479         }
2480       }
2481     } else {
2482       each(collection, callback, thisArg);
2483     }
2484     return collection;
2485   }
2486
2487   /**
2488    * Creates an object composed of keys returned from running each element of the
2489    * `collection` through the `callback`. The corresponding value of each key is
2490    * an array of elements passed to `callback` that returned the key. The `callback`
2491    * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
2492    *
2493    * If a property name is passed for `callback`, the created "_.pluck" style
2494    * callback will return the property value of the given element.
2495    *
2496    * If an object is passed for `callback`, the created "_.where" style callback
2497    * will return `true` for elements that have the propeties of the given object,
2498    * else `false`
2499    *
2500    * @static
2501    * @memberOf _
2502    * @category Collections
2503    * @param {Array|Object|String} collection The collection to iterate over.
2504    * @param {Function|Object|String} [callback=identity] The function called per
2505    *  iteration. If a property name or object is passed, it will be used to create
2506    *  a "_.pluck" or "_.where" style callback, respectively.
2507    * @param {Mixed} [thisArg] The `this` binding of `callback`.
2508    * @returns {Object} Returns the composed aggregate object.
2509    * @example
2510    *
2511    * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); });
2512    * // => { '4': [4.2], '6': [6.1, 6.4] }
2513    *
2514    * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
2515    * // => { '4': [4.2], '6': [6.1, 6.4] }
2516    *
2517    * // using "_.pluck" callback shorthand
2518    * _.groupBy(['one', 'two', 'three'], 'length');
2519    * // => { '3': ['one', 'two'], '5': ['three'] }
2520    */
2521   function groupBy(collection, callback, thisArg) {
2522     var result = {};
2523     callback = createCallback(callback, thisArg);
2524
2525     forEach(collection, function(value, key, collection) {
2526       key = callback(value, key, collection) + '';
2527       (hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value);
2528     });
2529     return result;
2530   }
2531
2532   /**
2533    * Invokes the method named by `methodName` on each element in the `collection`,
2534    * returning an array of the results of each invoked method. Additional arguments
2535    * will be passed to each invoked method. If `methodName` is a function, it will
2536    * be invoked for, and `this` bound to, each element in the `collection`.
2537    *
2538    * @static
2539    * @memberOf _
2540    * @category Collections
2541    * @param {Array|Object|String} collection The collection to iterate over.
2542    * @param {Function|String} methodName The name of the method to invoke or
2543    *  the function invoked per iteration.
2544    * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with.
2545    * @returns {Array} Returns a new array of the results of each invoked method.
2546    * @example
2547    *
2548    * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
2549    * // => [[1, 5, 7], [1, 2, 3]]
2550    *
2551    * _.invoke([123, 456], String.prototype.split, '');
2552    * // => [['1', '2', '3'], ['4', '5', '6']]
2553    */
2554   function invoke(collection, methodName) {
2555     var args = slice(arguments, 2),
2556         index = -1,
2557         isFunc = typeof methodName == 'function',
2558         length = collection ? collection.length : 0,
2559         result = Array(typeof length == 'number' ? length : 0);
2560
2561     forEach(collection, function(value) {
2562       result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args);
2563     });
2564     return result;
2565   }
2566
2567   /**
2568    * Creates an array of values by running each element in the `collection`
2569    * through the `callback`. The `callback` is bound to `thisArg` and invoked with
2570    * three arguments; (value, index|key, collection).
2571    *
2572    * If a property name is passed for `callback`, the created "_.pluck" style
2573    * callback will return the property value of the given element.
2574    *
2575    * If an object is passed for `callback`, the created "_.where" style callback
2576    * will return `true` for elements that have the propeties of the given object,
2577    * else `false`.
2578    *
2579    * @static
2580    * @memberOf _
2581    * @alias collect
2582    * @category Collections
2583    * @param {Array|Object|String} collection The collection to iterate over.
2584    * @param {Function|Object|String} [callback=identity] The function called per
2585    *  iteration. If a property name or object is passed, it will be used to create
2586    *  a "_.pluck" or "_.where" style callback, respectively.
2587    * @param {Mixed} [thisArg] The `this` binding of `callback`.
2588    * @returns {Array} Returns a new array of the results of each `callback` execution.
2589    * @example
2590    *
2591    * _.map([1, 2, 3], function(num) { return num * 3; });
2592    * // => [3, 6, 9]
2593    *
2594    * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
2595    * // => [3, 6, 9] (order is not guaranteed)
2596    *
2597    * var stooges = [
2598    *   { 'name': 'moe', 'age': 40 },
2599    *   { 'name': 'larry', 'age': 50 }
2600    * ];
2601    *
2602    * // using "_.pluck" callback shorthand
2603    * _.map(stooges, 'name');
2604    * // => ['moe', 'larry']
2605    */
2606   function map(collection, callback, thisArg) {
2607     var index = -1,
2608         length = collection ? collection.length : 0,
2609         result = Array(typeof length == 'number' ? length : 0);
2610
2611     callback = createCallback(callback, thisArg);
2612     if (isArray(collection)) {
2613       while (++index < length) {
2614         result[index] = callback(collection[index], index, collection);
2615       }
2616     } else {
2617       each(collection, function(value, key, collection) {
2618         result[++index] = callback(value, key, collection);
2619       });
2620     }
2621     return result;
2622   }
2623
2624   /**
2625    * Retrieves the maximum value of an `array`. If `callback` is passed,
2626    * it will be executed for each value in the `array` to generate the
2627    * criterion by which the value is ranked. The `callback` is bound to
2628    * `thisArg` and invoked with three arguments; (value, index, collection).
2629    *
2630    * If a property name is passed for `callback`, the created "_.pluck" style
2631    * callback will return the property value of the given element.
2632    *
2633    * If an object is passed for `callback`, the created "_.where" style callback
2634    * will return `true` for elements that have the propeties of the given object,
2635    * else `false`.
2636    *
2637    * @static
2638    * @memberOf _
2639    * @category Collections
2640    * @param {Array|Object|String} collection The collection to iterate over.
2641    * @param {Function|Object|String} [callback=identity] The function called per
2642    *  iteration. If a property name or object is passed, it will be used to create
2643    *  a "_.pluck" or "_.where" style callback, respectively.
2644    * @param {Mixed} [thisArg] The `this` binding of `callback`.
2645    * @returns {Mixed} Returns the maximum value.
2646    * @example
2647    *
2648    * _.max([4, 2, 8, 6]);
2649    * // => 8
2650    *
2651    * var stooges = [
2652    *   { 'name': 'moe', 'age': 40 },
2653    *   { 'name': 'larry', 'age': 50 }
2654    * ];
2655    *
2656    * _.max(stooges, function(stooge) { return stooge.age; });
2657    * // => { 'name': 'larry', 'age': 50 };
2658    *
2659    * // using "_.pluck" callback shorthand
2660    * _.max(stooges, 'age');
2661    * // => { 'name': 'larry', 'age': 50 };
2662    */
2663   function max(collection, callback, thisArg) {
2664     var computed = -Infinity,
2665         result = computed;
2666
2667     if (!callback && isArray(collection)) {
2668       var index = -1,
2669           length = collection.length;
2670
2671       while (++index < length) {
2672         var value = collection[index];
2673         if (value > result) {
2674           result = value;
2675         }
2676       }
2677     } else {
2678       callback = !callback && isString(collection)
2679         ? charAtCallback
2680         : createCallback(callback, thisArg);
2681
2682       each(collection, function(value, index, collection) {
2683         var current = callback(value, index, collection);
2684         if (current > computed) {
2685           computed = current;
2686           result = value;
2687         }
2688       });
2689     }
2690     return result;
2691   }
2692
2693   /**
2694    * Retrieves the minimum value of an `array`. If `callback` is passed,
2695    * it will be executed for each value in the `array` to generate the
2696    * criterion by which the value is ranked. The `callback` is bound to `thisArg`
2697    * and invoked with three arguments; (value, index, collection).
2698    *
2699    * If a property name is passed for `callback`, the created "_.pluck" style
2700    * callback will return the property value of the given element.
2701    *
2702    * If an object is passed for `callback`, the created "_.where" style callback
2703    * will return `true` for elements that have the propeties of the given object,
2704    * else `false`.
2705    *
2706    * @static
2707    * @memberOf _
2708    * @category Collections
2709    * @param {Array|Object|String} collection The collection to iterate over.
2710    * @param {Function|Object|String} [callback=identity] The function called per
2711    *  iteration. If a property name or object is passed, it will be used to create
2712    *  a "_.pluck" or "_.where" style callback, respectively.
2713    * @param {Mixed} [thisArg] The `this` binding of `callback`.
2714    * @returns {Mixed} Returns the minimum value.
2715    * @example
2716    *
2717    * _.min([4, 2, 8, 6]);
2718    * // => 2
2719    *
2720    * var stooges = [
2721    *   { 'name': 'moe', 'age': 40 },
2722    *   { 'name': 'larry', 'age': 50 }
2723    * ];
2724    *
2725    * _.min(stooges, function(stooge) { return stooge.age; });
2726    * // => { 'name': 'moe', 'age': 40 };
2727    *
2728    * // using "_.pluck" callback shorthand
2729    * _.min(stooges, 'age');
2730    * // => { 'name': 'moe', 'age': 40 };
2731    */
2732   function min(collection, callback, thisArg) {
2733     var computed = Infinity,
2734         result = computed;
2735
2736     if (!callback && isArray(collection)) {
2737       var index = -1,
2738           length = collection.length;
2739
2740       while (++index < length) {
2741         var value = collection[index];
2742         if (value < result) {
2743           result = value;
2744         }
2745       }
2746     } else {
2747       callback = !callback && isString(collection)
2748         ? charAtCallback
2749         : createCallback(callback, thisArg);
2750
2751       each(collection, function(value, index, collection) {
2752         var current = callback(value, index, collection);
2753         if (current < computed) {
2754           computed = current;
2755           result = value;
2756         }
2757       });
2758     }
2759     return result;
2760   }
2761
2762   /**
2763    * Retrieves the value of a specified property from all elements in the `collection`.
2764    *
2765    * @static
2766    * @memberOf _
2767    * @type Function
2768    * @category Collections
2769    * @param {Array|Object|String} collection The collection to iterate over.
2770    * @param {String} property The property to pluck.
2771    * @returns {Array} Returns a new array of property values.
2772    * @example
2773    *
2774    * var stooges = [
2775    *   { 'name': 'moe', 'age': 40 },
2776    *   { 'name': 'larry', 'age': 50 }
2777    * ];
2778    *
2779    * _.pluck(stooges, 'name');
2780    * // => ['moe', 'larry']
2781    */
2782   var pluck = map;
2783
2784   /**
2785    * Reduces a `collection` to a value that is the accumulated result of running
2786    * each element in the `collection` through the `callback`, where each successive
2787    * `callback` execution consumes the return value of the previous execution.
2788    * If `accumulator` is not passed, the first element of the `collection` will be
2789    * used as the initial `accumulator` value. The `callback` is bound to `thisArg`
2790    * and invoked with four arguments; (accumulator, value, index|key, collection).
2791    *
2792    * @static
2793    * @memberOf _
2794    * @alias foldl, inject
2795    * @category Collections
2796    * @param {Array|Object|String} collection The collection to iterate over.
2797    * @param {Function} [callback=identity] The function called per iteration.
2798    * @param {Mixed} [accumulator] Initial value of the accumulator.
2799    * @param {Mixed} [thisArg] The `this` binding of `callback`.
2800    * @returns {Mixed} Returns the accumulated value.
2801    * @example
2802    *
2803    * var sum = _.reduce([1, 2, 3], function(sum, num) {
2804    *   return sum + num;
2805    * });
2806    * // => 6
2807    *
2808    * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
2809    *   result[key] = num * 3;
2810    *   return result;
2811    * }, {});
2812    * // => { 'a': 3, 'b': 6, 'c': 9 }
2813    */
2814   function reduce(collection, callback, accumulator, thisArg) {
2815     var noaccum = arguments.length < 3;
2816     callback = createCallback(callback, thisArg, 4);
2817
2818     if (isArray(collection)) {
2819       var index = -1,
2820           length = collection.length;
2821
2822       if (noaccum) {
2823         accumulator = collection[++index];
2824       }
2825       while (++index < length) {
2826         accumulator = callback(accumulator, collection[index], index, collection);
2827       }
2828     } else {
2829       each(collection, function(value, index, collection) {
2830         accumulator = noaccum
2831           ? (noaccum = false, value)
2832           : callback(accumulator, value, index, collection)
2833       });
2834     }
2835     return accumulator;
2836   }
2837
2838   /**
2839    * This method is similar to `_.reduce`, except that it iterates over a
2840    * `collection` from right to left.
2841    *
2842    * @static
2843    * @memberOf _
2844    * @alias foldr
2845    * @category Collections
2846    * @param {Array|Object|String} collection The collection to iterate over.
2847    * @param {Function} [callback=identity] The function called per iteration.
2848    * @param {Mixed} [accumulator] Initial value of the accumulator.
2849    * @param {Mixed} [thisArg] The `this` binding of `callback`.
2850    * @returns {Mixed} Returns the accumulated value.
2851    * @example
2852    *
2853    * var list = [[0, 1], [2, 3], [4, 5]];
2854    * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
2855    * // => [4, 5, 2, 3, 0, 1]
2856    */
2857   function reduceRight(collection, callback, accumulator, thisArg) {
2858     var iterable = collection,
2859         length = collection ? collection.length : 0,
2860         noaccum = arguments.length < 3;
2861
2862     if (typeof length != 'number') {
2863       var props = keys(collection);
2864       length = props.length;
2865     } else if (noCharByIndex && isString(collection)) {
2866       iterable = collection.split('');
2867     }
2868     callback = createCallback(callback, thisArg, 4);
2869     forEach(collection, function(value, index, collection) {
2870       index = props ? props[--length] : --length;
2871       accumulator = noaccum
2872         ? (noaccum = false, iterable[index])
2873         : callback(accumulator, iterable[index], index, collection);
2874     });
2875     return accumulator;
2876   }
2877
2878   /**
2879    * The opposite of `_.filter`, this method returns the elements of a
2880    * `collection` that `callback` does **not** return truthy for.
2881    *
2882    * If a property name is passed for `callback`, the created "_.pluck" style
2883    * callback will return the property value of the given element.
2884    *
2885    * If an object is passed for `callback`, the created "_.where" style callback
2886    * will return `true` for elements that have the propeties of the given object,
2887    * else `false`.
2888    *
2889    * @static
2890    * @memberOf _
2891    * @category Collections
2892    * @param {Array|Object|String} collection The collection to iterate over.
2893    * @param {Function|Object|String} [callback=identity] The function called per
2894    *  iteration. If a property name or object is passed, it will be used to create
2895    *  a "_.pluck" or "_.where" style callback, respectively.
2896    * @param {Mixed} [thisArg] The `this` binding of `callback`.
2897    * @returns {Array} Returns a new array of elements that did **not** pass the
2898    *  callback check.
2899    * @example
2900    *
2901    * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
2902    * // => [1, 3, 5]
2903    *
2904    * var food = [
2905    *   { 'name': 'apple',  'organic': false, 'type': 'fruit' },
2906    *   { 'name': 'carrot', 'organic': true,  'type': 'vegetable' }
2907    * ];
2908    *
2909    * // using "_.pluck" callback shorthand
2910    * _.reject(food, 'organic');
2911    * // => [{ 'name': 'apple', 'organic': false, 'type': 'fruit' }]
2912    *
2913    * // using "_.where" callback shorthand
2914    * _.reject(food, { 'type': 'fruit' });
2915    * // => [{ 'name': 'carrot', 'organic': true, 'type': 'vegetable' }]
2916    */
2917   function reject(collection, callback, thisArg) {
2918     callback = createCallback(callback, thisArg);
2919     return filter(collection, function(value, index, collection) {
2920       return !callback(value, index, collection);
2921     });
2922   }
2923
2924   /**
2925    * Creates an array of shuffled `array` values, using a version of the
2926    * Fisher-Yates shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
2927    *
2928    * @static
2929    * @memberOf _
2930    * @category Collections
2931    * @param {Array|Object|String} collection The collection to shuffle.
2932    * @returns {Array} Returns a new shuffled collection.
2933    * @example
2934    *
2935    * _.shuffle([1, 2, 3, 4, 5, 6]);
2936    * // => [4, 1, 6, 3, 5, 2]
2937    */
2938   function shuffle(collection) {
2939     var index = -1,
2940         length = collection ? collection.length : 0,
2941         result = Array(typeof length == 'number' ? length : 0);
2942
2943     forEach(collection, function(value) {
2944       var rand = floor(nativeRandom() * (++index + 1));
2945       result[index] = result[rand];
2946       result[rand] = value;
2947     });
2948     return result;
2949   }
2950
2951   /**
2952    * Gets the size of the `collection` by returning `collection.length` for arrays
2953    * and array-like objects or the number of own enumerable properties for objects.
2954    *
2955    * @static
2956    * @memberOf _
2957    * @category Collections
2958    * @param {Array|Object|String} collection The collection to inspect.
2959    * @returns {Number} Returns `collection.length` or number of own enumerable properties.
2960    * @example
2961    *
2962    * _.size([1, 2]);
2963    * // => 2
2964    *
2965    * _.size({ 'one': 1, 'two': 2, 'three': 3 });
2966    * // => 3
2967    *
2968    * _.size('curly');
2969    * // => 5
2970    */
2971   function size(collection) {
2972     var length = collection ? collection.length : 0;
2973     return typeof length == 'number' ? length : keys(collection).length;
2974   }
2975
2976   /**
2977    * Checks if the `callback` returns a truthy value for **any** element of a
2978    * `collection`. The function returns as soon as it finds passing value, and
2979    * does not iterate over the entire `collection`. The `callback` is bound to
2980    * `thisArg` and invoked with three arguments; (value, index|key, collection).
2981    *
2982    * If a property name is passed for `callback`, the created "_.pluck" style
2983    * callback will return the property value of the given element.
2984    *
2985    * If an object is passed for `callback`, the created "_.where" style callback
2986    * will return `true` for elements that have the propeties of the given object,
2987    * else `false`.
2988    *
2989    * @static
2990    * @memberOf _
2991    * @alias any
2992    * @category Collections
2993    * @param {Array|Object|String} collection The collection to iterate over.
2994    * @param {Function|Object|String} [callback=identity] The function called per
2995    *  iteration. If a property name or object is passed, it will be used to create
2996    *  a "_.pluck" or "_.where" style callback, respectively.
2997    * @param {Mixed} [thisArg] The `this` binding of `callback`.
2998    * @returns {Boolean} Returns `true` if any element passes the callback check,
2999    *  else `false`.
3000    * @example
3001    *
3002    * _.some([null, 0, 'yes', false], Boolean);
3003    * // => true
3004    *
3005    * var food = [
3006    *   { 'name': 'apple',  'organic': false, 'type': 'fruit' },
3007    *   { 'name': 'carrot', 'organic': true,  'type': 'vegetable' }
3008    * ];
3009    *
3010    * // using "_.pluck" callback shorthand
3011    * _.some(food, 'organic');
3012    * // => true
3013    *
3014    * // using "_.where" callback shorthand
3015    * _.some(food, { 'type': 'meat' });
3016    * // => false
3017    */
3018   function some(collection, callback, thisArg) {
3019     var result;
3020     callback = createCallback(callback, thisArg);
3021
3022     if (isArray(collection)) {
3023       var index = -1,
3024           length = collection.length;
3025
3026       while (++index < length) {
3027         if ((result = callback(collection[index], index, collection))) {
3028           break;
3029         }
3030       }
3031     } else {
3032       each(collection, function(value, index, collection) {
3033         return !(result = callback(value, index, collection));
3034       });
3035     }
3036     return !!result;
3037   }
3038
3039   /**
3040    * Creates an array of elements, sorted in ascending order by the results of
3041    * running each element in the `collection` through the `callback`. This method
3042    * performs a stable sort, that is, it will preserve the original sort order of
3043    * equal elements. The `callback` is bound to `thisArg` and invoked with three
3044    * arguments; (value, index|key, collection).
3045    *
3046    * If a property name is passed for `callback`, the created "_.pluck" style
3047    * callback will return the property value of the given element.
3048    *
3049    * If an object is passed for `callback`, the created "_.where" style callback
3050    * will return `true` for elements that have the propeties of the given object,
3051    * else `false`.
3052    *
3053    * @static
3054    * @memberOf _
3055    * @category Collections
3056    * @param {Array|Object|String} collection The collection to iterate over.
3057    * @param {Function|Object|String} [callback=identity] The function called per
3058    *  iteration. If a property name or object is passed, it will be used to create
3059    *  a "_.pluck" or "_.where" style callback, respectively.
3060    * @param {Mixed} [thisArg] The `this` binding of `callback`.
3061    * @returns {Array} Returns a new array of sorted elements.
3062    * @example
3063    *
3064    * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); });
3065    * // => [3, 1, 2]
3066    *
3067    * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math);
3068    * // => [3, 1, 2]
3069    *
3070    * // using "_.pluck" callback shorthand
3071    * _.sortBy(['banana', 'strawberry', 'apple'], 'length');
3072    * // => ['apple', 'banana', 'strawberry']
3073    */
3074   function sortBy(collection, callback, thisArg) {
3075     var index = -1,
3076         length = collection ? collection.length : 0,
3077         result = Array(typeof length == 'number' ? length : 0);
3078
3079     callback = createCallback(callback, thisArg);
3080     forEach(collection, function(value, key, collection) {
3081       result[++index] = {
3082         'criteria': callback(value, key, collection),
3083         'index': index,
3084         'value': value
3085       };
3086     });
3087
3088     length = result.length;
3089     result.sort(compareAscending);
3090     while (length--) {
3091       result[length] = result[length].value;
3092     }
3093     return result;
3094   }
3095
3096   /**
3097    * Converts the `collection` to an array.
3098    *
3099    * @static
3100    * @memberOf _
3101    * @category Collections
3102    * @param {Array|Object|String} collection The collection to convert.
3103    * @returns {Array} Returns the new converted array.
3104    * @example
3105    *
3106    * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
3107    * // => [2, 3, 4]
3108    */
3109   function toArray(collection) {
3110     if (collection && typeof collection.length == 'number') {
3111       return noCharByIndex && isString(collection)
3112         ? collection.split('')
3113         : slice(collection);
3114     }
3115     return values(collection);
3116   }
3117
3118   /**
3119    * Examines each element in a `collection`, returning an array of all elements
3120    * that have the given `properties`. When checking `properties`, this method
3121    * performs a deep comparison between values to determine if they are equivalent
3122    * to each other.
3123    *
3124    * @static
3125    * @memberOf _
3126    * @type Function
3127    * @category Collections
3128    * @param {Array|Object|String} collection The collection to iterate over.
3129    * @param {Object} properties The object of property values to filter by.
3130    * @returns {Array} Returns a new array of elements that have the given `properties`.
3131    * @example
3132    *
3133    * var stooges = [
3134    *   { 'name': 'moe', 'age': 40 },
3135    *   { 'name': 'larry', 'age': 50 }
3136    * ];
3137    *
3138    * _.where(stooges, { 'age': 40 });
3139    * // => [{ 'name': 'moe', 'age': 40 }]
3140    */
3141   var where = filter;
3142
3143   /*--------------------------------------------------------------------------*/
3144
3145   /**
3146    * Creates an array with all falsey values of `array` removed. The values
3147    * `false`, `null`, `0`, `""`, `undefined` and `NaN` are all falsey.
3148    *
3149    * @static
3150    * @memberOf _
3151    * @category Arrays
3152    * @param {Array} array The array to compact.
3153    * @returns {Array} Returns a new filtered array.
3154    * @example
3155    *
3156    * _.compact([0, 1, false, 2, '', 3]);
3157    * // => [1, 2, 3]
3158    */
3159   function compact(array) {
3160     var index = -1,
3161         length = array ? array.length : 0,
3162         result = [];
3163
3164     while (++index < length) {
3165       var value = array[index];
3166       if (value) {
3167         result.push(value);
3168       }
3169     }
3170     return result;
3171   }
3172
3173   /**
3174    * Creates an array of `array` elements not present in the other arrays
3175    * using strict equality for comparisons, i.e. `===`.
3176    *
3177    * @static
3178    * @memberOf _
3179    * @category Arrays
3180    * @param {Array} array The array to process.
3181    * @param {Array} [array1, array2, ...] Arrays to check.
3182    * @returns {Array} Returns a new array of `array` elements not present in the
3183    *  other arrays.
3184    * @example
3185    *
3186    * _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
3187    * // => [1, 3, 4]
3188    */
3189   function difference(array) {
3190     var index = -1,
3191         length = array ? array.length : 0,
3192         flattened = concat.apply(arrayRef, arguments),
3193         contains = cachedContains(flattened, length),
3194         result = [];
3195
3196     while (++index < length) {
3197       var value = array[index];
3198       if (!contains(value)) {
3199         result.push(value);
3200       }
3201     }
3202     return result;
3203   }
3204
3205   /**
3206    * Gets the first element of the `array`. If a number `n` is passed, the first
3207    * `n` elements of the `array` are returned. If a `callback` function is passed,
3208    * the first elements the `callback` returns truthy for are returned. The `callback`
3209    * is bound to `thisArg` and invoked with three arguments; (value, index, array).
3210    *
3211    * If a property name is passed for `callback`, the created "_.pluck" style
3212    * callback will return the property value of the given element.
3213    *
3214    * If an object is passed for `callback`, the created "_.where" style callback
3215    * will return `true` for elements that have the propeties of the given object,
3216    * else `false`.
3217    *
3218    * @static
3219    * @memberOf _
3220    * @alias head, take
3221    * @category Arrays
3222    * @param {Array} array The array to query.
3223    * @param {Function|Object|Number|String} [callback|n] The function called
3224    *  per element or the number of elements to return. If a property name or
3225    *  object is passed, it will be used to create a "_.pluck" or "_.where"
3226    *  style callback, respectively.
3227    * @param {Mixed} [thisArg] The `this` binding of `callback`.
3228    * @returns {Mixed} Returns the first element(s) of `array`.
3229    * @example
3230    *
3231    * _.first([1, 2, 3]);
3232    * // => 1
3233    *
3234    * _.first([1, 2, 3], 2);
3235    * // => [1, 2]
3236    *
3237    * _.first([1, 2, 3], function(num) {
3238    *   return num < 3;
3239    * });
3240    * // => [1, 2]
3241    *
3242    * var food = [
3243    *   { 'name': 'banana', 'organic': true },
3244    *   { 'name': 'beet',   'organic': false },
3245    * ];
3246    *
3247    * // using "_.pluck" callback shorthand
3248    * _.first(food, 'organic');
3249    * // => [{ 'name': 'banana', 'organic': true }]
3250    *
3251    * var food = [
3252    *   { 'name': 'apple',  'type': 'fruit' },
3253    *   { 'name': 'banana', 'type': 'fruit' },
3254    *   { 'name': 'beet',   'type': 'vegetable' }
3255    * ];
3256    *
3257    * // using "_.where" callback shorthand
3258    * _.first(food, { 'type': 'fruit' });
3259    * // => [{ 'name': 'apple', 'type': 'fruit' }, { 'name': 'banana', 'type': 'fruit' }]
3260    */
3261   function first(array, callback, thisArg) {
3262     if (array) {
3263       var n = 0,
3264           length = array.length;
3265
3266       if (typeof callback != 'number' && callback != null) {
3267         var index = -1;
3268         callback = createCallback(callback, thisArg);
3269         while (++index < length && callback(array[index], index, array)) {
3270           n++;
3271         }
3272       } else {
3273         n = callback;
3274         if (n == null || thisArg) {
3275           return array[0];
3276         }
3277       }
3278       return slice(array, 0, nativeMin(nativeMax(0, n), length));
3279     }
3280   }
3281
3282   /**
3283    * Flattens a nested array (the nesting can be to any depth). If `shallow` is
3284    * truthy, `array` will only be flattened a single level.
3285    *
3286    * @static
3287    * @memberOf _
3288    * @category Arrays
3289    * @param {Array} array The array to compact.
3290    * @param {Boolean} shallow A flag to indicate only flattening a single level.
3291    * @returns {Array} Returns a new flattened array.
3292    * @example
3293    *
3294    * _.flatten([1, [2], [3, [[4]]]]);
3295    * // => [1, 2, 3, 4];
3296    *
3297    * _.flatten([1, [2], [3, [[4]]]], true);
3298    * // => [1, 2, 3, [[4]]];
3299    */
3300   function flatten(array, shallow) {
3301     var index = -1,
3302         length = array ? array.length : 0,
3303         result = [];
3304
3305     while (++index < length) {
3306       var value = array[index];
3307
3308       // recursively flatten arrays (susceptible to call stack limits)
3309       if (isArray(value)) {
3310         push.apply(result, shallow ? value : flatten(value));
3311       } else {
3312         result.push(value);
3313       }
3314     }
3315     return result;
3316   }
3317
3318   /**
3319    * Gets the index at which the first occurrence of `value` is found using
3320    * strict equality for comparisons, i.e. `===`. If the `array` is already
3321    * sorted, passing `true` for `fromIndex` will run a faster binary search.
3322    *
3323    * @static
3324    * @memberOf _
3325    * @category Arrays
3326    * @param {Array} array The array to search.
3327    * @param {Mixed} value The value to search for.
3328    * @param {Boolean|Number} [fromIndex=0] The index to search from or `true` to
3329    *  perform a binary search on a sorted `array`.
3330    * @returns {Number} Returns the index of the matched value or `-1`.
3331    * @example
3332    *
3333    * _.indexOf([1, 2, 3, 1, 2, 3], 2);
3334    * // => 1
3335    *
3336    * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3);
3337    * // => 4
3338    *
3339    * _.indexOf([1, 1, 2, 2, 3, 3], 2, true);
3340    * // => 2
3341    */
3342   function indexOf(array, value, fromIndex) {
3343     var index = -1,
3344         length = array ? array.length : 0;
3345
3346     if (typeof fromIndex == 'number') {
3347       index = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0) - 1;
3348     } else if (fromIndex) {
3349       index = sortedIndex(array, value);
3350       return array[index] === value ? index : -1;
3351     }
3352     while (++index < length) {
3353       if (array[index] === value) {
3354         return index;
3355       }
3356     }
3357     return -1;
3358   }
3359
3360   /**
3361    * Gets all but the last element of `array`. If a number `n` is passed, the
3362    * last `n` elements are excluded from the result. If a `callback` function
3363    * is passed, the last elements the `callback` returns truthy for are excluded
3364    * from the result. The `callback` is bound to `thisArg` and invoked with three
3365    * arguments; (value, index, array).
3366    *
3367    * If a property name is passed for `callback`, the created "_.pluck" style
3368    * callback will return the property value of the given element.
3369    *
3370    * If an object is passed for `callback`, the created "_.where" style callback
3371    * will return `true` for elements that have the propeties of the given object,
3372    * else `false`.
3373    *
3374    * @static
3375    * @memberOf _
3376    * @category Arrays
3377    * @param {Array} array The array to query.
3378    * @param {Function|Object|Number|String} [callback|n=1] The function called
3379    *  per element or the number of elements to exclude. If a property name or
3380    *  object is passed, it will be used to create a "_.pluck" or "_.where"
3381    *  style callback, respectively.
3382    * @param {Mixed} [thisArg] The `this` binding of `callback`.
3383    * @returns {Array} Returns a slice of `array`.
3384    * @example
3385    *
3386    * _.initial([1, 2, 3]);
3387    * // => [1, 2]
3388    *
3389    * _.initial([1, 2, 3], 2);
3390    * // => [1]
3391    *
3392    * _.initial([1, 2, 3], function(num) {
3393    *   return num > 1;
3394    * });
3395    * // => [1]
3396    *
3397    * var food = [
3398    *   { 'name': 'beet',   'organic': false },
3399    *   { 'name': 'carrot', 'organic': true }
3400    * ];
3401    *
3402    * // using "_.pluck" callback shorthand
3403    * _.initial(food, 'organic');
3404    * // => [{ 'name': 'beet',   'organic': false }]
3405    *
3406    * var food = [
3407    *   { 'name': 'banana', 'type': 'fruit' },
3408    *   { 'name': 'beet',   'type': 'vegetable' },
3409    *   { 'name': 'carrot', 'type': 'vegetable' }
3410    * ];
3411    *
3412    * // using "_.where" callback shorthand
3413    * _.initial(food, { 'type': 'vegetable' });
3414    * // => [{ 'name': 'banana', 'type': 'fruit' }]
3415    */
3416   function initial(array, callback, thisArg) {
3417     if (!array) {
3418       return [];
3419     }
3420     var n = 0,
3421         length = array.length;
3422
3423     if (typeof callback != 'number' && callback != null) {
3424       var index = length;
3425       callback = createCallback(callback, thisArg);
3426       while (index-- && callback(array[index], index, array)) {
3427         n++;
3428       }
3429     } else {
3430       n = (callback == null || thisArg) ? 1 : callback || n;
3431     }
3432     return slice(array, 0, nativeMin(nativeMax(0, length - n), length));
3433   }
3434
3435   /**
3436    * Computes the intersection of all the passed-in arrays using strict equality
3437    * for comparisons, i.e. `===`.
3438    *
3439    * @static
3440    * @memberOf _
3441    * @category Arrays
3442    * @param {Array} [array1, array2, ...] Arrays to process.
3443    * @returns {Array} Returns a new array of unique elements that are present
3444    *  in **all** of the arrays.
3445    * @example
3446    *
3447    * _.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
3448    * // => [1, 2]
3449    */
3450   function intersection(array) {
3451     var args = arguments,
3452         argsLength = args.length,
3453         cache = { '0': {} },
3454         index = -1,
3455         length = array ? array.length : 0,
3456         isLarge = length >= 100,
3457         result = [],
3458         seen = result;
3459
3460     outer:
3461     while (++index < length) {
3462       var value = array[index];
3463       if (isLarge) {
3464         var key = value + '';
3465         var inited = hasOwnProperty.call(cache[0], key)
3466           ? !(seen = cache[0][key])
3467           : (seen = cache[0][key] = []);
3468       }
3469       if (inited || indexOf(seen, value) < 0) {
3470         if (isLarge) {
3471           seen.push(value);
3472         }
3473         var argsIndex = argsLength;
3474         while (--argsIndex) {
3475           if (!(cache[argsIndex] || (cache[argsIndex] = cachedContains(args[argsIndex], 0, 100)))(value)) {
3476             continue outer;
3477           }
3478         }
3479         result.push(value);
3480       }
3481     }
3482     return result;
3483   }
3484
3485   /**
3486    * Gets the last element of the `array`. If a number `n` is passed, the last
3487    * `n` elements of the `array` are returned. If a `callback` function is passed,
3488    * the last elements the `callback` returns truthy for are returned. The `callback`
3489    * is bound to `thisArg` and invoked with three arguments; (value, index, array).
3490    *
3491    *
3492    * If a property name is passed for `callback`, the created "_.pluck" style
3493    * callback will return the property value of the given element.
3494    *
3495    * If an object is passed for `callback`, the created "_.where" style callback
3496    * will return `true` for elements that have the propeties of the given object,
3497    * else `false`.
3498    *
3499    * @static
3500    * @memberOf _
3501    * @category Arrays
3502    * @param {Array} array The array to query.
3503    * @param {Function|Object|Number|String} [callback|n] The function called
3504    *  per element or the number of elements to return. If a property name or
3505    *  object is passed, it will be used to create a "_.pluck" or "_.where"
3506    *  style callback, respectively.
3507    * @param {Mixed} [thisArg] The `this` binding of `callback`.
3508    * @returns {Mixed} Returns the last element(s) of `array`.
3509    * @example
3510    *
3511    * _.last([1, 2, 3]);
3512    * // => 3
3513    *
3514    * _.last([1, 2, 3], 2);
3515    * // => [2, 3]
3516    *
3517    * _.last([1, 2, 3], function(num) {
3518    *   return num > 1;
3519    * });
3520    * // => [2, 3]
3521    *
3522    * var food = [
3523    *   { 'name': 'beet',   'organic': false },
3524    *   { 'name': 'carrot', 'organic': true }
3525    * ];
3526    *
3527    * // using "_.pluck" callback shorthand
3528    * _.last(food, 'organic');
3529    * // => [{ 'name': 'carrot', 'organic': true }]
3530    *
3531    * var food = [
3532    *   { 'name': 'banana', 'type': 'fruit' },
3533    *   { 'name': 'beet',   'type': 'vegetable' },
3534    *   { 'name': 'carrot', 'type': 'vegetable' }
3535    * ];
3536    *
3537    * // using "_.where" callback shorthand
3538    * _.last(food, { 'type': 'vegetable' });
3539    * // => [{ 'name': 'beet', 'type': 'vegetable' }, { 'name': 'carrot', 'type': 'vegetable' }]
3540    */
3541   function last(array, callback, thisArg) {
3542     if (array) {
3543       var n = 0,
3544           length = array.length;
3545
3546       if (typeof callback != 'number' && callback != null) {
3547         var index = length;
3548         callback = createCallback(callback, thisArg);
3549         while (index-- && callback(array[index], index, array)) {
3550           n++;
3551         }
3552       } else {
3553         n = callback;
3554         if (n == null || thisArg) {
3555           return array[length - 1];
3556         }
3557       }
3558       return slice(array, nativeMax(0, length - n));
3559     }
3560   }
3561
3562   /**
3563    * Gets the index at which the last occurrence of `value` is found using strict
3564    * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
3565    * as the offset from the end of the collection.
3566    *
3567    * @static
3568    * @memberOf _
3569    * @category Arrays
3570    * @param {Array} array The array to search.
3571    * @param {Mixed} value The value to search for.
3572    * @param {Number} [fromIndex=array.length-1] The index to search from.
3573    * @returns {Number} Returns the index of the matched value or `-1`.
3574    * @example
3575    *
3576    * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
3577    * // => 4
3578    *
3579    * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);
3580    * // => 1
3581    */
3582   function lastIndexOf(array, value, fromIndex) {
3583     var index = array ? array.length : 0;
3584     if (typeof fromIndex == 'number') {
3585       index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1;
3586     }
3587     while (index--) {
3588       if (array[index] === value) {
3589         return index;
3590       }
3591     }
3592     return -1;
3593   }
3594
3595   /**
3596    * Creates an object composed from arrays of `keys` and `values`. Pass either
3597    * a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`, or
3598    * two arrays, one of `keys` and one of corresponding `values`.
3599    *
3600    * @static
3601    * @memberOf _
3602    * @category Arrays
3603    * @param {Array} keys The array of keys.
3604    * @param {Array} [values=[]] The array of values.
3605    * @returns {Object} Returns an object composed of the given keys and
3606    *  corresponding values.
3607    * @example
3608    *
3609    * _.object(['moe', 'larry'], [30, 40]);
3610    * // => { 'moe': 30, 'larry': 40 }
3611    */
3612   function object(keys, values) {
3613     var index = -1,
3614         length = keys ? keys.length : 0,
3615         result = {};
3616
3617     while (++index < length) {
3618       var key = keys[index];
3619       if (values) {
3620         result[key] = values[index];
3621       } else {
3622         result[key[0]] = key[1];
3623       }
3624     }
3625     return result;
3626   }
3627
3628   /**
3629    * Creates an array of numbers (positive and/or negative) progressing from
3630    * `start` up to but not including `end`.
3631    *
3632    * @static
3633    * @memberOf _
3634    * @category Arrays
3635    * @param {Number} [start=0] The start of the range.
3636    * @param {Number} end The end of the range.
3637    * @param {Number} [step=1] The value to increment or descrement by.
3638    * @returns {Array} Returns a new range array.
3639    * @example
3640    *
3641    * _.range(10);
3642    * // => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
3643    *
3644    * _.range(1, 11);
3645    * // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
3646    *
3647    * _.range(0, 30, 5);
3648    * // => [0, 5, 10, 15, 20, 25]
3649    *
3650    * _.range(0, -10, -1);
3651    * // => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
3652    *
3653    * _.range(0);
3654    * // => []
3655    */
3656   function range(start, end, step) {
3657     start = +start || 0;
3658     step = +step || 1;
3659
3660     if (end == null) {
3661       end = start;
3662       start = 0;
3663     }
3664     // use `Array(length)` so V8 will avoid the slower "dictionary" mode
3665     // http://youtu.be/XAqIpGU8ZZk#t=17m25s
3666     var index = -1,
3667         length = nativeMax(0, ceil((end - start) / step)),
3668         result = Array(length);
3669
3670     while (++index < length) {
3671       result[index] = start;
3672       start += step;
3673     }
3674     return result;
3675   }
3676
3677   /**
3678    * The opposite of `_.initial`, this method gets all but the first value of `array`.
3679    * If a number `n` is passed, the first `n` values are excluded from the result.
3680    * If a `callback` function is passed, the first elements the `callback` returns
3681    * truthy for are excluded from the result. The `callback` is bound to `thisArg`
3682    * and invoked with three arguments; (value, index, array).
3683    *
3684    * If a property name is passed for `callback`, the created "_.pluck" style
3685    * callback will return the property value of the given element.
3686    *
3687    * If an object is passed for `callback`, the created "_.where" style callback
3688    * will return `true` for elements that have the propeties of the given object,
3689    * else `false`.
3690    *
3691    * @static
3692    * @memberOf _
3693    * @alias drop, tail
3694    * @category Arrays
3695    * @param {Array} array The array to query.
3696    * @param {Function|Object|Number|String} [callback|n=1] The function called
3697    *  per element or the number of elements to exclude. If a property name or
3698    *  object is passed, it will be used to create a "_.pluck" or "_.where"
3699    *  style callback, respectively.
3700    * @param {Mixed} [thisArg] The `this` binding of `callback`.
3701    * @returns {Array} Returns a slice of `array`.
3702    * @example
3703    *
3704    * _.rest([1, 2, 3]);
3705    * // => [2, 3]
3706    *
3707    * _.rest([1, 2, 3], 2);
3708    * // => [3]
3709    *
3710    * _.rest([1, 2, 3], function(num) {
3711    *   return num < 3;
3712    * });
3713    * // => [3]
3714    *
3715    * var food = [
3716    *   { 'name': 'banana', 'organic': true },
3717    *   { 'name': 'beet',   'organic': false },
3718    * ];
3719    *
3720    * // using "_.pluck" callback shorthand
3721    * _.rest(food, 'organic');
3722    * // => [{ 'name': 'beet', 'organic': false }]
3723    *
3724    * var food = [
3725    *   { 'name': 'apple',  'type': 'fruit' },
3726    *   { 'name': 'banana', 'type': 'fruit' },
3727    *   { 'name': 'beet',   'type': 'vegetable' }
3728    * ];
3729    *
3730    * // using "_.where" callback shorthand
3731    * _.rest(food, { 'type': 'fruit' });
3732    * // => [{ 'name': 'beet', 'type': 'vegetable' }]
3733    */
3734   function rest(array, callback, thisArg) {
3735     if (typeof callback != 'number' && callback != null) {
3736       var n = 0,
3737           index = -1,
3738           length = array ? array.length : 0;
3739
3740       callback = createCallback(callback, thisArg);
3741       while (++index < length && callback(array[index], index, array)) {
3742         n++;
3743       }
3744     } else {
3745       n = (callback == null || thisArg) ? 1 : nativeMax(0, callback);
3746     }
3747     return slice(array, n);
3748   }
3749
3750   /**
3751    * Uses a binary search to determine the smallest index at which the `value`
3752    * should be inserted into `array` in order to maintain the sort order of the
3753    * sorted `array`. If `callback` is passed, it will be executed for `value` and
3754    * each element in `array` to compute their sort ranking. The `callback` is
3755    * bound to `thisArg` and invoked with one argument; (value).
3756    *
3757    * If a property name is passed for `callback`, the created "_.pluck" style
3758    * callback will return the property value of the given element.
3759    *
3760    * If an object is passed for `callback`, the created "_.where" style callback
3761    * will return `true` for elements that have the propeties of the given object,
3762    * else `false`.
3763    *
3764    * @static
3765    * @memberOf _
3766    * @category Arrays
3767    * @param {Array} array The array to iterate over.
3768    * @param {Mixed} value The value to evaluate.
3769    * @param {Function|Object|String} [callback=identity] The function called per
3770    *  iteration. If a property name or object is passed, it will be used to create
3771    *  a "_.pluck" or "_.where" style callback, respectively.
3772    * @param {Mixed} [thisArg] The `this` binding of `callback`.
3773    * @returns {Number} Returns the index at which the value should be inserted
3774    *  into `array`.
3775    * @example
3776    *
3777    * _.sortedIndex([20, 30, 50], 40);
3778    * // => 2
3779    *
3780    * // using "_.pluck" callback shorthand
3781    * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
3782    * // => 2
3783    *
3784    * var dict = {
3785    *   'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 }
3786    * };
3787    *
3788    * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
3789    *   return dict.wordToNumber[word];
3790    * });
3791    * // => 2
3792    *
3793    * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
3794    *   return this.wordToNumber[word];
3795    * }, dict);
3796    * // => 2
3797    */
3798   function sortedIndex(array, value, callback, thisArg) {
3799     var low = 0,
3800         high = array ? array.length : low;
3801
3802     // explicitly reference `identity` for better inlining in Firefox
3803     callback = callback ? createCallback(callback, thisArg, 1) : identity;
3804     value = callback(value);
3805
3806     while (low < high) {
3807       var mid = (low + high) >>> 1;
3808       callback(array[mid]) < value
3809         ? low = mid + 1
3810         : high = mid;
3811     }
3812     return low;
3813   }
3814
3815   /**
3816    * Computes the union of the passed-in arrays using strict equality for
3817    * comparisons, i.e. `===`.
3818    *
3819    * @static
3820    * @memberOf _
3821    * @category Arrays
3822    * @param {Array} [array1, array2, ...] Arrays to process.
3823    * @returns {Array} Returns a new array of unique values, in order, that are
3824    *  present in one or more of the arrays.
3825    * @example
3826    *
3827    * _.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
3828    * // => [1, 2, 3, 101, 10]
3829    */
3830   function union() {
3831     return uniq(concat.apply(arrayRef, arguments));
3832   }
3833
3834   /**
3835    * Creates a duplicate-value-free version of the `array` using strict equality
3836    * for comparisons, i.e. `===`. If the `array` is already sorted, passing `true`
3837    * for `isSorted` will run a faster algorithm. If `callback` is passed, each
3838    * element of `array` is passed through a callback` before uniqueness is computed.
3839    * The `callback` is bound to `thisArg` and invoked with three arguments; (value, index, array).
3840    *
3841    * If a property name is passed for `callback`, the created "_.pluck" style
3842    * callback will return the property value of the given element.
3843    *
3844    * If an object is passed for `callback`, the created "_.where" style callback
3845    * will return `true` for elements that have the propeties of the given object,
3846    * else `false`.
3847    *
3848    * @static
3849    * @memberOf _
3850    * @alias unique
3851    * @category Arrays
3852    * @param {Array} array The array to process.
3853    * @param {Boolean} [isSorted=false] A flag to indicate that the `array` is already sorted.
3854    * @param {Function|Object|String} [callback=identity] The function called per
3855    *  iteration. If a property name or object is passed, it will be used to create
3856    *  a "_.pluck" or "_.where" style callback, respectively.
3857    * @param {Mixed} [thisArg] The `this` binding of `callback`.
3858    * @returns {Array} Returns a duplicate-value-free array.
3859    * @example
3860    *
3861    * _.uniq([1, 2, 1, 3, 1]);
3862    * // => [1, 2, 3]
3863    *
3864    * _.uniq([1, 1, 2, 2, 3], true);
3865    * // => [1, 2, 3]
3866    *
3867    * _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return Math.floor(num); });
3868    * // => [1, 2, 3]
3869    *
3870    * _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return this.floor(num); }, Math);
3871    * // => [1, 2, 3]
3872    *
3873    * // using "_.pluck" callback shorthand
3874    * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
3875    * // => [{ 'x': 1 }, { 'x': 2 }]
3876    */
3877   function uniq(array, isSorted, callback, thisArg) {
3878     var index = -1,
3879         length = array ? array.length : 0,
3880         result = [],
3881         seen = result;
3882
3883     // juggle arguments
3884     if (typeof isSorted == 'function') {
3885       thisArg = callback;
3886       callback = isSorted;
3887       isSorted = false;
3888     }
3889     // init value cache for large arrays
3890     var isLarge = !isSorted && length >= 75;
3891     if (isLarge) {
3892       var cache = {};
3893     }
3894     if (callback) {
3895       seen = [];
3896       callback = createCallback(callback, thisArg);
3897     }
3898     while (++index < length) {
3899       var value = array[index],
3900           computed = callback ? callback(value, index, array) : value;
3901
3902       if (isLarge) {
3903         var key = computed + '';
3904         var inited = hasOwnProperty.call(cache, key)
3905           ? !(seen = cache[key])
3906           : (seen = cache[key] = []);
3907       }
3908       if (isSorted
3909             ? !index || seen[seen.length - 1] !== computed
3910             : inited || indexOf(seen, computed) < 0
3911           ) {
3912         if (callback || isLarge) {
3913           seen.push(computed);
3914         }
3915         result.push(value);
3916       }
3917     }
3918     return result;
3919   }
3920
3921   /**
3922    * Creates an array with all occurrences of the passed values removed using
3923    * strict equality for comparisons, i.e. `===`.
3924    *
3925    * @static
3926    * @memberOf _
3927    * @category Arrays
3928    * @param {Array} array The array to filter.
3929    * @param {Mixed} [value1, value2, ...] Values to remove.
3930    * @returns {Array} Returns a new filtered array.
3931    * @example
3932    *
3933    * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
3934    * // => [2, 3, 4]
3935    */
3936   function without(array) {
3937     var index = -1,
3938         length = array ? array.length : 0,
3939         contains = cachedContains(arguments, 1),
3940         result = [];
3941
3942     while (++index < length) {
3943       var value = array[index];
3944       if (!contains(value)) {
3945         result.push(value);
3946       }
3947     }
3948     return result;
3949   }
3950
3951   /**
3952    * Groups the elements of each array at their corresponding indexes. Useful for
3953    * separate data sources that are coordinated through matching array indexes.
3954    * For a matrix of nested arrays, `_.zip.apply(...)` can transpose the matrix
3955    * in a similar fashion.
3956    *
3957    * @static
3958    * @memberOf _
3959    * @category Arrays
3960    * @param {Array} [array1, array2, ...] Arrays to process.
3961    * @returns {Array} Returns a new array of grouped elements.
3962    * @example
3963    *
3964    * _.zip(['moe', 'larry'], [30, 40], [true, false]);
3965    * // => [['moe', 30, true], ['larry', 40, false]]
3966    */
3967   function zip(array) {
3968     var index = -1,
3969         length = array ? max(pluck(arguments, 'length')) : 0,
3970         result = Array(length);
3971
3972     while (++index < length) {
3973       result[index] = pluck(arguments, index);
3974     }
3975     return result;
3976   }
3977
3978   /*--------------------------------------------------------------------------*/
3979
3980   /**
3981    * Creates a function that is restricted to executing `func` only after it is
3982    * called `n` times. The `func` is executed with the `this` binding of the
3983    * created function.
3984    *
3985    * @static
3986    * @memberOf _
3987    * @category Functions
3988    * @param {Number} n The number of times the function must be called before
3989    * it is executed.
3990    * @param {Function} func The function to restrict.
3991    * @returns {Function} Returns the new restricted function.
3992    * @example
3993    *
3994    * var renderNotes = _.after(notes.length, render);
3995    * _.forEach(notes, function(note) {
3996    *   note.asyncSave({ 'success': renderNotes });
3997    * });
3998    * // `renderNotes` is run once, after all notes have saved
3999    */
4000   function after(n, func) {
4001     if (n < 1) {
4002       return func();
4003     }
4004     return function() {
4005       if (--n < 1) {
4006         return func.apply(this, arguments);
4007       }
4008     };
4009   }
4010
4011   /**
4012    * Creates a function that, when called, invokes `func` with the `this`
4013    * binding of `thisArg` and prepends any additional `bind` arguments to those
4014    * passed to the bound function.
4015    *
4016    * @static
4017    * @memberOf _
4018    * @category Functions
4019    * @param {Function} func The function to bind.
4020    * @param {Mixed} [thisArg] The `this` binding of `func`.
4021    * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
4022    * @returns {Function} Returns the new bound function.
4023    * @example
4024    *
4025    * var func = function(greeting) {
4026    *   return greeting + ' ' + this.name;
4027    * };
4028    *
4029    * func = _.bind(func, { 'name': 'moe' }, 'hi');
4030    * func();
4031    * // => 'hi moe'
4032    */
4033   function bind(func, thisArg) {
4034     // use `Function#bind` if it exists and is fast
4035     // (in V8 `Function#bind` is slower except when partially applied)
4036     return isBindFast || (nativeBind && arguments.length > 2)
4037       ? nativeBind.call.apply(nativeBind, arguments)
4038       : createBound(func, thisArg, slice(arguments, 2));
4039   }
4040
4041   /**
4042    * Binds methods on `object` to `object`, overwriting the existing method.
4043    * Method names may be specified as individual arguments or as arrays of method
4044    * names. If no method names are provided, all the function properties of `object`
4045    * will be bound.
4046    *
4047    * @static
4048    * @memberOf _
4049    * @category Functions
4050    * @param {Object} object The object to bind and assign the bound methods to.
4051    * @param {String} [methodName1, methodName2, ...] Method names on the object to bind.
4052    * @returns {Object} Returns `object`.
4053    * @example
4054    *
4055    * var view = {
4056    *  'label': 'docs',
4057    *  'onClick': function() { alert('clicked ' + this.label); }
4058    * };
4059    *
4060    * _.bindAll(view);
4061    * jQuery('#docs').on('click', view.onClick);
4062    * // => alerts 'clicked docs', when the button is clicked
4063    */
4064   function bindAll(object) {
4065     var funcs = concat.apply(arrayRef, arguments),
4066         index = funcs.length > 1 ? 0 : (funcs = functions(object), -1),
4067         length = funcs.length;
4068
4069     while (++index < length) {
4070       var key = funcs[index];
4071       object[key] = bind(object[key], object);
4072     }
4073     return object;
4074   }
4075
4076   /**
4077    * Creates a function that, when called, invokes the method at `object[key]`
4078    * and prepends any additional `bindKey` arguments to those passed to the bound
4079    * function. This method differs from `_.bind` by allowing bound functions to
4080    * reference methods that will be redefined or don't yet exist.
4081    * See http://michaux.ca/articles/lazy-function-definition-pattern.
4082    *
4083    * @static
4084    * @memberOf _
4085    * @category Functions
4086    * @param {Object} object The object the method belongs to.
4087    * @param {String} key The key of the method.
4088    * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
4089    * @returns {Function} Returns the new bound function.
4090    * @example
4091    *
4092    * var object = {
4093    *   'name': 'moe',
4094    *   'greet': function(greeting) {
4095    *     return greeting + ' ' + this.name;
4096    *   }
4097    * };
4098    *
4099    * var func = _.bindKey(object, 'greet', 'hi');
4100    * func();
4101    * // => 'hi moe'
4102    *
4103    * object.greet = function(greeting) {
4104    *   return greeting + ', ' + this.name + '!';
4105    * };
4106    *
4107    * func();
4108    * // => 'hi, moe!'
4109    */
4110   function bindKey(object, key) {
4111     return createBound(object, key, slice(arguments, 2));
4112   }
4113
4114   /**
4115    * Creates a function that is the composition of the passed functions,
4116    * where each function consumes the return value of the function that follows.
4117    * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
4118    * Each function is executed with the `this` binding of the composed function.
4119    *
4120    * @static
4121    * @memberOf _
4122    * @category Functions
4123    * @param {Function} [func1, func2, ...] Functions to compose.
4124    * @returns {Function} Returns the new composed function.
4125    * @example
4126    *
4127    * var greet = function(name) { return 'hi ' + name; };
4128    * var exclaim = function(statement) { return statement + '!'; };
4129    * var welcome = _.compose(exclaim, greet);
4130    * welcome('moe');
4131    * // => 'hi moe!'
4132    */
4133   function compose() {
4134     var funcs = arguments;
4135     return function() {
4136       var args = arguments,
4137           length = funcs.length;
4138
4139       while (length--) {
4140         args = [funcs[length].apply(this, args)];
4141       }
4142       return args[0];
4143     };
4144   }
4145
4146   /**
4147    * Creates a function that will delay the execution of `func` until after
4148    * `wait` milliseconds have elapsed since the last time it was invoked. Pass
4149    * `true` for `immediate` to cause debounce to invoke `func` on the leading,
4150    * instead of the trailing, edge of the `wait` timeout. Subsequent calls to
4151    * the debounced function will return the result of the last `func` call.
4152    *
4153    * @static
4154    * @memberOf _
4155    * @category Functions
4156    * @param {Function} func The function to debounce.
4157    * @param {Number} wait The number of milliseconds to delay.
4158    * @param {Boolean} immediate A flag to indicate execution is on the leading
4159    *  edge of the timeout.
4160    * @returns {Function} Returns the new debounced function.
4161    * @example
4162    *
4163    * var lazyLayout = _.debounce(calculateLayout, 300);
4164    * jQuery(window).on('resize', lazyLayout);
4165    */
4166   function debounce(func, wait, immediate) {
4167     var args,
4168         result,
4169         thisArg,
4170         timeoutId;
4171
4172     function delayed() {
4173       timeoutId = null;
4174       if (!immediate) {
4175         result = func.apply(thisArg, args);
4176       }
4177     }
4178     return function() {
4179       var isImmediate = immediate && !timeoutId;
4180       args = arguments;
4181       thisArg = this;
4182
4183       clearTimeout(timeoutId);
4184       timeoutId = setTimeout(delayed, wait);
4185
4186       if (isImmediate) {
4187         result = func.apply(thisArg, args);
4188       }
4189       return result;
4190     };
4191   }
4192
4193   /**
4194    * Executes the `func` function after `wait` milliseconds. Additional arguments
4195    * will be passed to `func` when it is invoked.
4196    *
4197    * @static
4198    * @memberOf _
4199    * @category Functions
4200    * @param {Function} func The function to delay.
4201    * @param {Number} wait The number of milliseconds to delay execution.
4202    * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with.
4203    * @returns {Number} Returns the `setTimeout` timeout id.
4204    * @example
4205    *
4206    * var log = _.bind(console.log, console);
4207    * _.delay(log, 1000, 'logged later');
4208    * // => 'logged later' (Appears after one second.)
4209    */
4210   function delay(func, wait) {
4211     var args = slice(arguments, 2);
4212     return setTimeout(function() { func.apply(undefined, args); }, wait);
4213   }
4214
4215   /**
4216    * Defers executing the `func` function until the current call stack has cleared.
4217    * Additional arguments will be passed to `func` when it is invoked.
4218    *
4219    * @static
4220    * @memberOf _
4221    * @category Functions
4222    * @param {Function} func The function to defer.
4223    * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with.
4224    * @returns {Number} Returns the `setTimeout` timeout id.
4225    * @example
4226    *
4227    * _.defer(function() { alert('deferred'); });
4228    * // returns from the function before `alert` is called
4229    */
4230   function defer(func) {
4231     var args = slice(arguments, 1);
4232     return setTimeout(function() { func.apply(undefined, args); }, 1);
4233   }
4234   // use `setImmediate` if it's available in Node.js
4235   if (isV8 && freeModule && typeof setImmediate == 'function') {
4236     defer = bind(setImmediate, window);
4237   }
4238
4239   /**
4240    * Creates a function that memoizes the result of `func`. If `resolver` is
4241    * passed, it will be used to determine the cache key for storing the result
4242    * based on the arguments passed to the memoized function. By default, the first
4243    * argument passed to the memoized function is used as the cache key. The `func`
4244    * is executed with the `this` binding of the memoized function.
4245    *
4246    * @static
4247    * @memberOf _
4248    * @category Functions
4249    * @param {Function} func The function to have its output memoized.
4250    * @param {Function} [resolver] A function used to resolve the cache key.
4251    * @returns {Function} Returns the new memoizing function.
4252    * @example
4253    *
4254    * var fibonacci = _.memoize(function(n) {
4255    *   return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
4256    * });
4257    */
4258   function memoize(func, resolver) {
4259     var cache = {};
4260     return function() {
4261       var key = (resolver ? resolver.apply(this, arguments) : arguments[0]) + '';
4262       return hasOwnProperty.call(cache, key)
4263         ? cache[key]
4264         : (cache[key] = func.apply(this, arguments));
4265     };
4266   }
4267
4268   /**
4269    * Creates a function that is restricted to execute `func` once. Repeat calls to
4270    * the function will return the value of the first call. The `func` is executed
4271    * with the `this` binding of the created function.
4272    *
4273    * @static
4274    * @memberOf _
4275    * @category Functions
4276    * @param {Function} func The function to restrict.
4277    * @returns {Function} Returns the new restricted function.
4278    * @example
4279    *
4280    * var initialize = _.once(createApplication);
4281    * initialize();
4282    * initialize();
4283    * // `initialize` executes `createApplication` once
4284    */
4285   function once(func) {
4286     var ran,
4287         result;
4288
4289     return function() {
4290       if (ran) {
4291         return result;
4292       }
4293       ran = true;
4294       result = func.apply(this, arguments);
4295
4296       // clear the `func` variable so the function may be garbage collected
4297       func = null;
4298       return result;
4299     };
4300   }
4301
4302   /**
4303    * Creates a function that, when called, invokes `func` with any additional
4304    * `partial` arguments prepended to those passed to the new function. This
4305    * method is similar to `_.bind`, except it does **not** alter the `this` binding.
4306    *
4307    * @static
4308    * @memberOf _
4309    * @category Functions
4310    * @param {Function} func The function to partially apply arguments to.
4311    * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
4312    * @returns {Function} Returns the new partially applied function.
4313    * @example
4314    *
4315    * var greet = function(greeting, name) { return greeting + ' ' + name; };
4316    * var hi = _.partial(greet, 'hi');
4317    * hi('moe');
4318    * // => 'hi moe'
4319    */
4320   function partial(func) {
4321     return createBound(func, slice(arguments, 1));
4322   }
4323
4324   /**
4325    * This method is similar to `_.partial`, except that `partial` arguments are
4326    * appended to those passed to the new function.
4327    *
4328    * @static
4329    * @memberOf _
4330    * @category Functions
4331    * @param {Function} func The function to partially apply arguments to.
4332    * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
4333    * @returns {Function} Returns the new partially applied function.
4334    * @example
4335    *
4336    * var defaultsDeep = _.partialRight(_.merge, _.defaults);
4337    *
4338    * var options = {
4339    *   'variable': 'data',
4340    *   'imports': { 'jq': $ }
4341    * };
4342    *
4343    * defaultsDeep(options, _.templateSettings);
4344    *
4345    * options.variable
4346    * // => 'data'
4347    *
4348    * options.imports
4349    * // => { '_': _, 'jq': $ }
4350    */
4351   function partialRight(func) {
4352     return createBound(func, slice(arguments, 1), null, indicatorObject);
4353   }
4354
4355   /**
4356    * Creates a function that, when executed, will only call the `func`
4357    * function at most once per every `wait` milliseconds. If the throttled
4358    * function is invoked more than once during the `wait` timeout, `func` will
4359    * also be called on the trailing edge of the timeout. Subsequent calls to the
4360    * throttled function will return the result of the last `func` call.
4361    *
4362    * @static
4363    * @memberOf _
4364    * @category Functions
4365    * @param {Function} func The function to throttle.
4366    * @param {Number} wait The number of milliseconds to throttle executions to.
4367    * @returns {Function} Returns the new throttled function.
4368    * @example
4369    *
4370    * var throttled = _.throttle(updatePosition, 100);
4371    * jQuery(window).on('scroll', throttled);
4372    */
4373   function throttle(func, wait) {
4374     var args,
4375         result,
4376         thisArg,
4377         timeoutId,
4378         lastCalled = 0;
4379
4380     function trailingCall() {
4381       lastCalled = new Date;
4382       timeoutId = null;
4383       result = func.apply(thisArg, args);
4384     }
4385     return function() {
4386       var now = new Date,
4387           remaining = wait - (now - lastCalled);
4388
4389       args = arguments;
4390       thisArg = this;
4391
4392       if (remaining <= 0) {
4393         clearTimeout(timeoutId);
4394         timeoutId = null;
4395         lastCalled = now;
4396         result = func.apply(thisArg, args);
4397       }
4398       else if (!timeoutId) {
4399         timeoutId = setTimeout(trailingCall, remaining);
4400       }
4401       return result;
4402     };
4403   }
4404
4405   /**
4406    * Creates a function that passes `value` to the `wrapper` function as its
4407    * first argument. Additional arguments passed to the function are appended
4408    * to those passed to the `wrapper` function. The `wrapper` is executed with
4409    * the `this` binding of the created function.
4410    *
4411    * @static
4412    * @memberOf _
4413    * @category Functions
4414    * @param {Mixed} value The value to wrap.
4415    * @param {Function} wrapper The wrapper function.
4416    * @returns {Function} Returns the new function.
4417    * @example
4418    *
4419    * var hello = function(name) { return 'hello ' + name; };
4420    * hello = _.wrap(hello, function(func) {
4421    *   return 'before, ' + func('moe') + ', after';
4422    * });
4423    * hello();
4424    * // => 'before, hello moe, after'
4425    */
4426   function wrap(value, wrapper) {
4427     return function() {
4428       var args = [value];
4429       push.apply(args, arguments);
4430       return wrapper.apply(this, args);
4431     };
4432   }
4433
4434   /*--------------------------------------------------------------------------*/
4435
4436   /**
4437    * Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their
4438    * corresponding HTML entities.
4439    *
4440    * @static
4441    * @memberOf _
4442    * @category Utilities
4443    * @param {String} string The string to escape.
4444    * @returns {String} Returns the escaped string.
4445    * @example
4446    *
4447    * _.escape('Moe, Larry & Curly');
4448    * // => 'Moe, Larry &amp; Curly'
4449    */
4450   function escape(string) {
4451     return string == null ? '' : (string + '').replace(reUnescapedHtml, escapeHtmlChar);
4452   }
4453
4454   /**
4455    * This function returns the first argument passed to it.
4456    *
4457    * @static
4458    * @memberOf _
4459    * @category Utilities
4460    * @param {Mixed} value Any value.
4461    * @returns {Mixed} Returns `value`.
4462    * @example
4463    *
4464    * var moe = { 'name': 'moe' };
4465    * moe === _.identity(moe);
4466    * // => true
4467    */
4468   function identity(value) {
4469     return value;
4470   }
4471
4472   /**
4473    * Adds functions properties of `object` to the `lodash` function and chainable
4474    * wrapper.
4475    *
4476    * @static
4477    * @memberOf _
4478    * @category Utilities
4479    * @param {Object} object The object of function properties to add to `lodash`.
4480    * @example
4481    *
4482    * _.mixin({
4483    *   'capitalize': function(string) {
4484    *     return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
4485    *   }
4486    * });
4487    *
4488    * _.capitalize('moe');
4489    * // => 'Moe'
4490    *
4491    * _('moe').capitalize();
4492    * // => 'Moe'
4493    */
4494   function mixin(object) {
4495     forEach(functions(object), function(methodName) {
4496       var func = lodash[methodName] = object[methodName];
4497
4498       lodash.prototype[methodName] = function() {
4499         var args = [this.__wrapped__];
4500         push.apply(args, arguments);
4501         return new lodash(func.apply(lodash, args));
4502       };
4503     });
4504   }
4505
4506   /**
4507    * Reverts the '_' variable to its previous value and returns a reference to
4508    * the `lodash` function.
4509    *
4510    * @static
4511    * @memberOf _
4512    * @category Utilities
4513    * @returns {Function} Returns the `lodash` function.
4514    * @example
4515    *
4516    * var lodash = _.noConflict();
4517    */
4518   function noConflict() {
4519     window._ = oldDash;
4520     return this;
4521   }
4522
4523   /**
4524    * Produces a random number between `min` and `max` (inclusive). If only one
4525    * argument is passed, a number between `0` and the given number will be returned.
4526    *
4527    * @static
4528    * @memberOf _
4529    * @category Utilities
4530    * @param {Number} [min=0] The minimum possible value.
4531    * @param {Number} [max=1] The maximum possible value.
4532    * @returns {Number} Returns a random number.
4533    * @example
4534    *
4535    * _.random(0, 5);
4536    * // => a number between 0 and 5
4537    *
4538    * _.random(5);
4539    * // => also a number between 0 and 5
4540    */
4541   function random(min, max) {
4542     if (min == null && max == null) {
4543       max = 1;
4544     }
4545     min = +min || 0;
4546     if (max == null) {
4547       max = min;
4548       min = 0;
4549     }
4550     return min + floor(nativeRandom() * ((+max || 0) - min + 1));
4551   }
4552
4553   /**
4554    * Resolves the value of `property` on `object`. If `property` is a function,
4555    * it will be invoked and its result returned, else the property value is
4556    * returned. If `object` is falsey, then `null` is returned.
4557    *
4558    * @static
4559    * @memberOf _
4560    * @category Utilities
4561    * @param {Object} object The object to inspect.
4562    * @param {String} property The property to get the value of.
4563    * @returns {Mixed} Returns the resolved value.
4564    * @example
4565    *
4566    * var object = {
4567    *   'cheese': 'crumpets',
4568    *   'stuff': function() {
4569    *     return 'nonsense';
4570    *   }
4571    * };
4572    *
4573    * _.result(object, 'cheese');
4574    * // => 'crumpets'
4575    *
4576    * _.result(object, 'stuff');
4577    * // => 'nonsense'
4578    */
4579   function result(object, property) {
4580     var value = object ? object[property] : undefined;
4581     return isFunction(value) ? object[property]() : value;
4582   }
4583
4584   /**
4585    * A micro-templating method that handles arbitrary delimiters, preserves
4586    * whitespace, and correctly escapes quotes within interpolated code.
4587    *
4588    * Note: In the development build, `_.template` utilizes sourceURLs for easier
4589    * debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
4590    *
4591    * Note: Lo-Dash may be used in Chrome extensions by either creating a `lodash csp`
4592    * build and using precompiled templates, or loading Lo-Dash in a sandbox.
4593    *
4594    * For more information on precompiling templates see:
4595    * http://lodash.com/#custom-builds
4596    *
4597    * For more information on Chrome extension sandboxes see:
4598    * http://developer.chrome.com/stable/extensions/sandboxingEval.html
4599    *
4600    * @static
4601    * @memberOf _
4602    * @category Utilities
4603    * @param {String} text The template text.
4604    * @param {Obect} data The data object used to populate the text.
4605    * @param {Object} options The options object.
4606    *  escape - The "escape" delimiter regexp.
4607    *  evaluate - The "evaluate" delimiter regexp.
4608    *  interpolate - The "interpolate" delimiter regexp.
4609    *  sourceURL - The sourceURL of the template's compiled source.
4610    *  variable - The data object variable name.
4611    *
4612    * @returns {Function|String} Returns a compiled function when no `data` object
4613    *  is given, else it returns the interpolated text.
4614    * @example
4615    *
4616    * // using a compiled template
4617    * var compiled = _.template('hello <%= name %>');
4618    * compiled({ 'name': 'moe' });
4619    * // => 'hello moe'
4620    *
4621    * var list = '<% _.forEach(people, function(name) { %><li><%= name %></li><% }); %>';
4622    * _.template(list, { 'people': ['moe', 'larry'] });
4623    * // => '<li>moe</li><li>larry</li>'
4624    *
4625    * // using the "escape" delimiter to escape HTML in data property values
4626    * _.template('<b><%- value %></b>', { 'value': '<script>' });
4627    * // => '<b>&lt;script&gt;</b>'
4628    *
4629    * // using the ES6 delimiter as an alternative to the default "interpolate" delimiter
4630    * _.template('hello ${ name }', { 'name': 'curly' });
4631    * // => 'hello curly'
4632    *
4633    * // using the internal `print` function in "evaluate" delimiters
4634    * _.template('<% print("hello " + epithet); %>!', { 'epithet': 'stooge' });
4635    * // => 'hello stooge!'
4636    *
4637    * // using custom template delimiters
4638    * _.templateSettings = {
4639    *   'interpolate': /{{([\s\S]+?)}}/g
4640    * };
4641    *
4642    * _.template('hello {{ name }}!', { 'name': 'mustache' });
4643    * // => 'hello mustache!'
4644    *
4645    * // using the `sourceURL` option to specify a custom sourceURL for the template
4646    * var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' });
4647    * compiled(data);
4648    * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
4649    *
4650    * // using the `variable` option to ensure a with-statement isn't used in the compiled template
4651    * var compiled = _.template('hi <%= data.name %>!', null, { 'variable': 'data' });
4652    * compiled.source;
4653    * // => function(data) {
4654    *   var __t, __p = '', __e = _.escape;
4655    *   __p += 'hi ' + ((__t = ( data.name )) == null ? '' : __t) + '!';
4656    *   return __p;
4657    * }
4658    *
4659    * // using the `source` property to inline compiled templates for meaningful
4660    * // line numbers in error messages and a stack trace
4661    * fs.writeFileSync(path.join(cwd, 'jst.js'), '\
4662    *   var JST = {\
4663    *     "main": ' + _.template(mainText).source + '\
4664    *   };\
4665    * ');
4666    */
4667   function template(text, data, options) {
4668     // based on John Resig's `tmpl` implementation
4669     // http://ejohn.org/blog/javascript-micro-templating/
4670     // and Laura Doktorova's doT.js
4671     // https://github.com/olado/doT
4672     var settings = lodash.templateSettings;
4673     text || (text = '');
4674
4675     // avoid missing dependencies when `iteratorTemplate` is not defined
4676     options = defaults({}, options, settings);
4677
4678     var imports = defaults({}, options.imports, settings.imports),
4679         importsKeys = keys(imports),
4680         importsValues = values(imports);
4681
4682     var isEvaluating,
4683         index = 0,
4684         interpolate = options.interpolate || reNoMatch,
4685         source = "__p += '";
4686
4687     // compile regexp to match each delimiter
4688     var reDelimiters = RegExp(
4689       (options.escape || reNoMatch).source + '|' +
4690       interpolate.source + '|' +
4691       (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
4692       (options.evaluate || reNoMatch).source + '|$'
4693     , 'g');
4694
4695     text.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
4696       interpolateValue || (interpolateValue = esTemplateValue);
4697
4698       // escape characters that cannot be included in string literals
4699       source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);
4700
4701       // replace delimiters with snippets
4702       if (escapeValue) {
4703         source += "' +\n__e(" + escapeValue + ") +\n'";
4704       }
4705       if (evaluateValue) {
4706         isEvaluating = true;
4707         source += "';\n" + evaluateValue + ";\n__p += '";
4708       }
4709       if (interpolateValue) {
4710         source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
4711       }
4712       index = offset + match.length;
4713
4714       // the JS engine embedded in Adobe products requires returning the `match`
4715       // string in order to produce the correct `offset` value
4716       return match;
4717     });
4718
4719     source += "';\n";
4720
4721     // if `variable` is not specified and the template contains "evaluate"
4722     // delimiters, wrap a with-statement around the generated code to add the
4723     // data object to the top of the scope chain
4724     var variable = options.variable,
4725         hasVariable = variable;
4726
4727     if (!hasVariable) {
4728       variable = 'obj';
4729       source = 'with (' + variable + ') {\n' + source + '\n}\n';
4730     }
4731     // cleanup code by stripping empty strings
4732     source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
4733       .replace(reEmptyStringMiddle, '$1')
4734       .replace(reEmptyStringTrailing, '$1;');
4735
4736     // frame code as the function body
4737     source = 'function(' + variable + ') {\n' +
4738       (hasVariable ? '' : variable + ' || (' + variable + ' = {});\n') +
4739       "var __t, __p = '', __e = _.escape" +
4740       (isEvaluating
4741         ? ', __j = Array.prototype.join;\n' +
4742           "function print() { __p += __j.call(arguments, '') }\n"
4743         : ';\n'
4744       ) +
4745       source +
4746       'return __p\n}';
4747
4748     // Use a sourceURL for easier debugging and wrap in a multi-line comment to
4749     // avoid issues with Narwhal, IE conditional compilation, and the JS engine
4750     // embedded in Adobe products.
4751     // http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
4752     var sourceURL = '\n/*\n//@ sourceURL=' + (options.sourceURL || '/lodash/template/source[' + (templateCounter++) + ']') + '\n*/';
4753
4754     try {
4755       var result = Function(importsKeys, 'return ' + source + sourceURL).apply(undefined, importsValues);
4756     } catch(e) {
4757       e.source = source;
4758       throw e;
4759     }
4760     if (data) {
4761       return result(data);
4762     }
4763     // provide the compiled function's source via its `toString` method, in
4764     // supported environments, or the `source` property as a convenience for
4765     // inlining compiled templates during the build process
4766     result.source = source;
4767     return result;
4768   }
4769
4770   /**
4771    * Executes the `callback` function `n` times, returning an array of the results
4772    * of each `callback` execution. The `callback` is bound to `thisArg` and invoked
4773    * with one argument; (index).
4774    *
4775    * @static
4776    * @memberOf _
4777    * @category Utilities
4778    * @param {Number} n The number of times to execute the callback.
4779    * @param {Function} callback The function called per iteration.
4780    * @param {Mixed} [thisArg] The `this` binding of `callback`.
4781    * @returns {Array} Returns a new array of the results of each `callback` execution.
4782    * @example
4783    *
4784    * var diceRolls = _.times(3, _.partial(_.random, 1, 6));
4785    * // => [3, 6, 4]
4786    *
4787    * _.times(3, function(n) { mage.castSpell(n); });
4788    * // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively
4789    *
4790    * _.times(3, function(n) { this.cast(n); }, mage);
4791    * // => also calls `mage.castSpell(n)` three times
4792    */
4793   function times(n, callback, thisArg) {
4794     n = +n || 0;
4795     var index = -1,
4796         result = Array(n);
4797
4798     while (++index < n) {
4799       result[index] = callback.call(thisArg, index);
4800     }
4801     return result;
4802   }
4803
4804   /**
4805    * The opposite of `_.escape`, this method converts the HTML entities
4806    * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to their
4807    * corresponding characters.
4808    *
4809    * @static
4810    * @memberOf _
4811    * @category Utilities
4812    * @param {String} string The string to unescape.
4813    * @returns {String} Returns the unescaped string.
4814    * @example
4815    *
4816    * _.unescape('Moe, Larry &amp; Curly');
4817    * // => 'Moe, Larry & Curly'
4818    */
4819   function unescape(string) {
4820     return string == null ? '' : (string + '').replace(reEscapedHtml, unescapeHtmlChar);
4821   }
4822
4823   /**
4824    * Generates a unique ID. If `prefix` is passed, the ID will be appended to it.
4825    *
4826    * @static
4827    * @memberOf _
4828    * @category Utilities
4829    * @param {String} [prefix] The value to prefix the ID with.
4830    * @returns {String} Returns the unique ID.
4831    * @example
4832    *
4833    * _.uniqueId('contact_');
4834    * // => 'contact_104'
4835    *
4836    * _.uniqueId();
4837    * // => '105'
4838    */
4839   function uniqueId(prefix) {
4840     var id = ++idCounter;
4841     return (prefix == null ? '' : prefix + '') + id;
4842   }
4843
4844   /*--------------------------------------------------------------------------*/
4845
4846   /**
4847    * Invokes `interceptor` with the `value` as the first argument, and then
4848    * returns `value`. The purpose of this method is to "tap into" a method chain,
4849    * in order to perform operations on intermediate results within the chain.
4850    *
4851    * @static
4852    * @memberOf _
4853    * @category Chaining
4854    * @param {Mixed} value The value to pass to `interceptor`.
4855    * @param {Function} interceptor The function to invoke.
4856    * @returns {Mixed} Returns `value`.
4857    * @example
4858    *
4859    * _([1, 2, 3, 4])
4860    *  .filter(function(num) { return num % 2 == 0; })
4861    *  .tap(alert)
4862    *  .map(function(num) { return num * num; })
4863    *  .value();
4864    * // => // [2, 4] (alerted)
4865    * // => [4, 16]
4866    */
4867   function tap(value, interceptor) {
4868     interceptor(value);
4869     return value;
4870   }
4871
4872   /**
4873    * Produces the `toString` result of the wrapped value.
4874    *
4875    * @name toString
4876    * @memberOf _
4877    * @category Chaining
4878    * @returns {String} Returns the string result.
4879    * @example
4880    *
4881    * _([1, 2, 3]).toString();
4882    * // => '1,2,3'
4883    */
4884   function wrapperToString() {
4885     return this.__wrapped__ + '';
4886   }
4887
4888   /**
4889    * Extracts the wrapped value.
4890    *
4891    * @name valueOf
4892    * @memberOf _
4893    * @alias value
4894    * @category Chaining
4895    * @returns {Mixed} Returns the wrapped value.
4896    * @example
4897    *
4898    * _([1, 2, 3]).valueOf();
4899    * // => [1, 2, 3]
4900    */
4901   function wrapperValueOf() {
4902     return this.__wrapped__;
4903   }
4904
4905   /*--------------------------------------------------------------------------*/
4906
4907   // add functions that return wrapped values when chaining
4908   lodash.after = after;
4909   lodash.assign = assign;
4910   lodash.at = at;
4911   lodash.bind = bind;
4912   lodash.bindAll = bindAll;
4913   lodash.bindKey = bindKey;
4914   lodash.compact = compact;
4915   lodash.compose = compose;
4916   lodash.countBy = countBy;
4917   lodash.debounce = debounce;
4918   lodash.defaults = defaults;
4919   lodash.defer = defer;
4920   lodash.delay = delay;
4921   lodash.difference = difference;
4922   lodash.filter = filter;
4923   lodash.flatten = flatten;
4924   lodash.forEach = forEach;
4925   lodash.forIn = forIn;
4926   lodash.forOwn = forOwn;
4927   lodash.functions = functions;
4928   lodash.groupBy = groupBy;
4929   lodash.initial = initial;
4930   lodash.intersection = intersection;
4931   lodash.invert = invert;
4932   lodash.invoke = invoke;
4933   lodash.keys = keys;
4934   lodash.map = map;
4935   lodash.max = max;
4936   lodash.memoize = memoize;
4937   lodash.merge = merge;
4938   lodash.min = min;
4939   lodash.object = object;
4940   lodash.omit = omit;
4941   lodash.once = once;
4942   lodash.pairs = pairs;
4943   lodash.partial = partial;
4944   lodash.partialRight = partialRight;
4945   lodash.pick = pick;
4946   lodash.pluck = pluck;
4947   lodash.range = range;
4948   lodash.reject = reject;
4949   lodash.rest = rest;
4950   lodash.shuffle = shuffle;
4951   lodash.sortBy = sortBy;
4952   lodash.tap = tap;
4953   lodash.throttle = throttle;
4954   lodash.times = times;
4955   lodash.toArray = toArray;
4956   lodash.union = union;
4957   lodash.uniq = uniq;
4958   lodash.values = values;
4959   lodash.where = where;
4960   lodash.without = without;
4961   lodash.wrap = wrap;
4962   lodash.zip = zip;
4963
4964   // add aliases
4965   lodash.collect = map;
4966   lodash.drop = rest;
4967   lodash.each = forEach;
4968   lodash.extend = assign;
4969   lodash.methods = functions;
4970   lodash.select = filter;
4971   lodash.tail = rest;
4972   lodash.unique = uniq;
4973
4974   // add functions to `lodash.prototype`
4975   mixin(lodash);
4976
4977   /*--------------------------------------------------------------------------*/
4978
4979   // add functions that return unwrapped values when chaining
4980   lodash.clone = clone;
4981   lodash.cloneDeep = cloneDeep;
4982   lodash.contains = contains;
4983   lodash.escape = escape;
4984   lodash.every = every;
4985   lodash.find = find;
4986   lodash.has = has;
4987   lodash.identity = identity;
4988   lodash.indexOf = indexOf;
4989   lodash.isArguments = isArguments;
4990   lodash.isArray = isArray;
4991   lodash.isBoolean = isBoolean;
4992   lodash.isDate = isDate;
4993   lodash.isElement = isElement;
4994   lodash.isEmpty = isEmpty;
4995   lodash.isEqual = isEqual;
4996   lodash.isFinite = isFinite;
4997   lodash.isFunction = isFunction;
4998   lodash.isNaN = isNaN;
4999   lodash.isNull = isNull;
5000   lodash.isNumber = isNumber;
5001   lodash.isObject = isObject;
5002   lodash.isPlainObject = isPlainObject;
5003   lodash.isRegExp = isRegExp;
5004   lodash.isString = isString;
5005   lodash.isUndefined = isUndefined;
5006   lodash.lastIndexOf = lastIndexOf;
5007   lodash.mixin = mixin;
5008   lodash.noConflict = noConflict;
5009   lodash.random = random;
5010   lodash.reduce = reduce;
5011   lodash.reduceRight = reduceRight;
5012   lodash.result = result;
5013   lodash.size = size;
5014   lodash.some = some;
5015   lodash.sortedIndex = sortedIndex;
5016   lodash.template = template;
5017   lodash.unescape = unescape;
5018   lodash.uniqueId = uniqueId;
5019
5020   // add aliases
5021   lodash.all = every;
5022   lodash.any = some;
5023   lodash.detect = find;
5024   lodash.foldl = reduce;
5025   lodash.foldr = reduceRight;
5026   lodash.include = contains;
5027   lodash.inject = reduce;
5028
5029   forOwn(lodash, function(func, methodName) {
5030     if (!lodash.prototype[methodName]) {
5031       lodash.prototype[methodName] = function() {
5032         var args = [this.__wrapped__];
5033         push.apply(args, arguments);
5034         return func.apply(lodash, args);
5035       };
5036     }
5037   });
5038
5039   /*--------------------------------------------------------------------------*/
5040
5041   // add functions capable of returning wrapped and unwrapped values when chaining
5042   lodash.first = first;
5043   lodash.last = last;
5044
5045   // add aliases
5046   lodash.take = first;
5047   lodash.head = first;
5048
5049   forOwn(lodash, function(func, methodName) {
5050     if (!lodash.prototype[methodName]) {
5051       lodash.prototype[methodName]= function(callback, thisArg) {
5052         var result = func(this.__wrapped__, callback, thisArg);
5053         return callback == null || (thisArg && typeof callback != 'function')
5054           ? result
5055           : new lodash(result);
5056       };
5057     }
5058   });
5059
5060   /*--------------------------------------------------------------------------*/
5061
5062   /**
5063    * The semantic version number.
5064    *
5065    * @static
5066    * @memberOf _
5067    * @type String
5068    */
5069   lodash.VERSION = '1.0.2';
5070
5071   // add "Chaining" functions to the wrapper
5072   lodash.prototype.toString = wrapperToString;
5073   lodash.prototype.value = wrapperValueOf;
5074   lodash.prototype.valueOf = wrapperValueOf;
5075
5076   // add `Array` functions that return unwrapped values
5077   each(['join', 'pop', 'shift'], function(methodName) {
5078     var func = arrayRef[methodName];
5079     lodash.prototype[methodName] = function() {
5080       return func.apply(this.__wrapped__, arguments);
5081     };
5082   });
5083
5084   // add `Array` functions that return the wrapped value
5085   each(['push', 'reverse', 'sort', 'unshift'], function(methodName) {
5086     var func = arrayRef[methodName];
5087     lodash.prototype[methodName] = function() {
5088       func.apply(this.__wrapped__, arguments);
5089       return this;
5090     };
5091   });
5092
5093   // add `Array` functions that return new wrapped values
5094   each(['concat', 'slice', 'splice'], function(methodName) {
5095     var func = arrayRef[methodName];
5096     lodash.prototype[methodName] = function() {
5097       return new lodash(func.apply(this.__wrapped__, arguments));
5098     };
5099   });
5100
5101   // avoid array-like object bugs with `Array#shift` and `Array#splice`
5102   // in Firefox < 10 and IE < 9
5103   if (hasObjectSpliceBug) {
5104     each(['pop', 'shift', 'splice'], function(methodName) {
5105       var func = arrayRef[methodName],
5106           isSplice = methodName == 'splice';
5107
5108       lodash.prototype[methodName] = function() {
5109         var value = this.__wrapped__,
5110             result = func.apply(value, arguments);
5111
5112         if (value.length === 0) {
5113           delete value[0];
5114         }
5115         return isSplice ? new lodash(result) : result;
5116       };
5117     });
5118   }
5119
5120   /*--------------------------------------------------------------------------*/
5121
5122   // expose Lo-Dash
5123   // some AMD build optimizers, like r.js, check for specific condition patterns like the following:
5124   if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
5125     // Expose Lo-Dash to the global object even when an AMD loader is present in
5126     // case Lo-Dash was injected by a third-party script and not intended to be
5127     // loaded as a module. The global assignment can be reverted in the Lo-Dash
5128     // module via its `noConflict()` method.
5129     window._ = lodash;
5130
5131     // define as an anonymous module so, through path mapping, it can be
5132     // referenced as the "underscore" module
5133     define(function() {
5134       return lodash;
5135     });
5136   }
5137   // check for `exports` after `define` in case a build optimizer adds an `exports` object
5138   else if (freeExports) {
5139     // in Node.js or RingoJS v0.8.0+
5140     if (freeModule) {
5141       (freeModule.exports = lodash)._ = lodash;
5142     }
5143     // in Narwhal or RingoJS v0.7.0-
5144     else {
5145       freeExports._ = lodash;
5146     }
5147   }
5148   else {
5149     // in a browser or Rhino
5150     window._ = lodash;
5151   }
5152 }(this));