lodash-rails 0.7.0

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