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