lodash-rails 1.0.0.rc.3 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -18,6 +18,6 @@ Add the necessary library to `app/assets/javascripts/application.js`:
18
18
 
19
19
  ## What's included?
20
20
 
21
- * Lo-Dash 1.0.0-rc.3 (lodash, lodash.min)
21
+ * Lo-Dash 1.0.1 (lodash, lodash.min)
22
22
 
23
23
  Copyright Richard Hubers, released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  module LoDash
2
2
  module Rails
3
- VERSION = "1.0.0.rc.3"
3
+ VERSION = "1.0.1"
4
4
  end
5
5
  end
@@ -1,8 +1,10 @@
1
- /*!
2
- * Lo-Dash 1.0.0-rc.3 <http://lodash.com>
3
- * (c) 2012 John-David Dalton <http://allyoucanleet.com/>
4
- * Based on Underscore.js 1.4.3 <http://underscorejs.org>
5
- * (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
1
+ /**
2
+ * @license
3
+ * Lo-Dash 1.0.1 (Custom Build) <http://lodash.com/>
4
+ * Build: `lodash modern -o ./dist/lodash.js`
5
+ * Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
6
+ * Based on Underscore.js 1.4.4 <http://underscorejs.org/>
7
+ * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
6
8
  * Available under MIT license <http://lodash.com/license>
7
9
  */
8
10
  ;(function(window, undefined) {
@@ -10,6 +12,9 @@
10
12
  /** Detect free variable `exports` */
11
13
  var freeExports = typeof exports == 'object' && exports;
12
14
 
15
+ /** Detect free variable `module` */
16
+ var freeModule = typeof module == 'object' && module && module.exports == freeExports && module;
17
+
13
18
  /** Detect free variable `global` and use it as `window` */
14
19
  var freeGlobal = typeof global == 'object' && global;
15
20
  if (freeGlobal.global === freeGlobal) {
@@ -18,8 +23,7 @@
18
23
 
19
24
  /** Used for array and object method references */
20
25
  var arrayRef = [],
21
- // avoid a Closure Compiler bug by creatively creating an object
22
- objectRef = new function(){};
26
+ objectRef = {};
23
27
 
24
28
  /** Used to generate unique IDs */
25
29
  var idCounter = 0;
@@ -33,11 +37,8 @@
33
37
  /** Used to restore the original `_` reference in `noConflict` */
34
38
  var oldDash = window._;
35
39
 
36
- /** Used to detect template delimiter values that require a with-statement */
37
- var reComplexDelimiter = /[-?+=!~*%&^<>|{(\/]|\[\D|\b(?:delete|in|instanceof|new|typeof|void)\b/;
38
-
39
40
  /** Used to match HTML entities */
40
- var reEscapedHtml = /&(?:amp|lt|gt|quot|#x27);/g;
41
+ var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g;
41
42
 
42
43
  /** Used to match empty string literals in compiled template source */
43
44
  var reEmptyStringLeading = /\b__p \+= '';/g,
@@ -47,13 +48,10 @@
47
48
  /** Used to match regexp flags from their coerced string values */
48
49
  var reFlags = /\w*$/;
49
50
 
50
- /** Used to insert the data object variable into compiled template source */
51
- var reInsertVariable = /(?:__e|__t = )\(\s*(?![\d\s"']|this\.)/g;
52
-
53
51
  /** Used to detect if a method is native */
54
52
  var reNative = RegExp('^' +
55
53
  (objectRef.valueOf + '')
56
- .replace(/[.*+?^=!:${}()|[\]\/\\]/g, '\\$&')
54
+ .replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
57
55
  .replace(/valueOf|for [^\]]+/g, '.+?') + '$'
58
56
  );
59
57
 
@@ -61,7 +59,7 @@
61
59
  * Used to match ES6 template delimiters
62
60
  * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6
63
61
  */
64
- var reEsTemplate = /\$\{((?:(?=\\?)\\?[\s\S])*?)}/g;
62
+ var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
65
63
 
66
64
  /** Used to match "interpolate" template delimiters */
67
65
  var reInterpolate = /<%=([\s\S]+?)%>/g;
@@ -75,12 +73,6 @@
75
73
  /** Used to match unescaped characters in compiled string literals */
76
74
  var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
77
75
 
78
- /** Used to fix the JScript [[DontEnum]] bug */
79
- var shadowed = [
80
- 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',
81
- 'toLocaleString', 'toString', 'valueOf'
82
- ];
83
-
84
76
  /** Used to make template sourceURLs easier to identify */
85
77
  var templateCounter = 0;
86
78
 
@@ -91,7 +83,6 @@
91
83
  getPrototypeOf = reNative.test(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,
92
84
  hasOwnProperty = objectRef.hasOwnProperty,
93
85
  push = arrayRef.push,
94
- propertyIsEnumerable = objectRef.propertyIsEnumerable,
95
86
  toString = objectRef.toString;
96
87
 
97
88
  /* Native method shortcuts for methods with the same name as other `lodash` methods */
@@ -125,84 +116,6 @@
125
116
  /* Detect if `Object.keys` exists and is inferred to be fast (IE, Opera, V8) */
126
117
  var isKeysFast = nativeKeys && (isIeOpera || isV8);
127
118
 
128
- /**
129
- * Detect the JScript [[DontEnum]] bug:
130
- *
131
- * In IE < 9 an objects own properties, shadowing non-enumerable ones, are
132
- * made non-enumerable as well.
133
- */
134
- var hasDontEnumBug;
135
-
136
- /** Detect if own properties are iterated after inherited properties (IE < 9) */
137
- var iteratesOwnLast;
138
-
139
- /**
140
- * Detect if `Array#shift` and `Array#splice` augment array-like objects
141
- * incorrectly:
142
- *
143
- * Firefox < 10, IE compatibility mode, and IE < 9 have buggy Array `shift()`
144
- * and `splice()` functions that fail to remove the last element, `value[0]`,
145
- * of array-like objects even though the `length` property is set to `0`.
146
- * The `shift()` method is buggy in IE 8 compatibility mode, while `splice()`
147
- * is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9.
148
- */
149
- var hasObjectSpliceBug = (hasObjectSpliceBug = { '0': 1, 'length': 1 },
150
- arrayRef.splice.call(hasObjectSpliceBug, 0, 1), hasObjectSpliceBug[0]);
151
-
152
- /** Detect if an `arguments` object's indexes are non-enumerable (IE < 9) */
153
- var nonEnumArgs = true;
154
-
155
- (function() {
156
- var props = [];
157
- function ctor() { this.x = 1; }
158
- ctor.prototype = { 'valueOf': 1, 'y': 1 };
159
- for (var prop in new ctor) { props.push(prop); }
160
- for (prop in arguments) { nonEnumArgs = !prop; }
161
-
162
- hasDontEnumBug = !/valueOf/.test(props);
163
- iteratesOwnLast = props[0] != 'x';
164
- }(1));
165
-
166
- /** Detect if `arguments` objects are `Object` objects (all but Opera < 10.5) */
167
- var argsAreObjects = arguments.constructor == Object;
168
-
169
- /** Detect if `arguments` objects [[Class]] is unresolvable (Firefox < 4, IE < 9) */
170
- var noArgsClass = !isArguments(arguments);
171
-
172
- /**
173
- * Detect lack of support for accessing string characters by index:
174
- *
175
- * IE < 8 can't access characters by index and IE 8 can only access
176
- * characters by index on string literals.
177
- */
178
- var noCharByIndex = ('x'[0] + Object('x')[0]) != 'xx';
179
-
180
- /**
181
- * Detect if a node's [[Class]] is unresolvable (IE < 9)
182
- * and that the JS engine won't error when attempting to coerce an object to
183
- * a string without a `toString` property value of `typeof` "function".
184
- */
185
- try {
186
- var noNodeClass = ({ 'toString': 0 } + '', toString.call(document) == objectClass);
187
- } catch(e) { }
188
-
189
- /**
190
- * Detect if sourceURL syntax is usable without erroring:
191
- *
192
- * The JS engine embedded in Adobe products will throw a syntax error when
193
- * it encounters a single line comment beginning with the `@` symbol.
194
- *
195
- * The JS engine in Narwhal will generate the function `function anonymous(){//}`
196
- * and throw a syntax error.
197
- *
198
- * Avoid comments beginning `@` symbols in IE because they are part of its
199
- * non-standard conditional compilation support.
200
- * http://msdn.microsoft.com/en-us/library/121hztk3(v=vs.94).aspx
201
- */
202
- try {
203
- var useSourceURL = (Function('//@')(), !isIeOpera);
204
- } catch(e) { }
205
-
206
119
  /** Used to identify object classifications that `_.clone` supports */
207
120
  var cloneableClasses = {};
208
121
  cloneableClasses[funcClass] = false;
@@ -245,18 +158,22 @@
245
158
  /*--------------------------------------------------------------------------*/
246
159
 
247
160
  /**
248
- * Creates a `lodash` object, that wraps the given `value`, to enable
249
- * method chaining.
161
+ * Creates a `lodash` object, that wraps the given `value`, to enable method
162
+ * chaining.
163
+ *
164
+ * In addition to Lo-Dash methods, wrappers also have the following `Array` methods:
165
+ * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`,
166
+ * and `unshift`
250
167
  *
251
168
  * The chainable wrapper functions are:
252
169
  * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`, `compose`,
253
170
  * `concat`, `countBy`, `debounce`, `defaults`, `defer`, `delay`, `difference`,
254
171
  * `filter`, `flatten`, `forEach`, `forIn`, `forOwn`, `functions`, `groupBy`,
255
172
  * `initial`, `intersection`, `invert`, `invoke`, `keys`, `map`, `max`, `memoize`,
256
- * `merge`, `min`, `object`, `omit`, `once`, `pairs`, `partial`, `pick`, `pluck`,
257
- * `push`, `range`, `reject`, `rest`, `reverse`, `shuffle`, `slice`, `sort`,
258
- * `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `union`, `uniq`,
259
- * `unshift`, `values`, `where`, `without`, `wrap`, and `zip`
173
+ * `merge`, `min`, `object`, `omit`, `once`, `pairs`, `partial`, `partialRight`,
174
+ * `pick`, `pluck`, `push`, `range`, `reject`, `rest`, `reverse`, `shuffle`,
175
+ * `slice`, `sort`, `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`,
176
+ * `union`, `uniq`, `unshift`, `values`, `where`, `without`, `wrap`, and `zip`
260
177
  *
261
178
  * The non-chainable wrapper functions are:
262
179
  * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `has`, `identity`,
@@ -301,7 +218,6 @@
301
218
  /**
302
219
  * Used to detect `data` property values to be HTML-escaped.
303
220
  *
304
- * @static
305
221
  * @memberOf _.templateSettings
306
222
  * @type RegExp
307
223
  */
@@ -310,7 +226,6 @@
310
226
  /**
311
227
  * Used to detect code to be evaluated.
312
228
  *
313
- * @static
314
229
  * @memberOf _.templateSettings
315
230
  * @type RegExp
316
231
  */
@@ -319,7 +234,6 @@
319
234
  /**
320
235
  * Used to detect `data` property values to inject.
321
236
  *
322
- * @static
323
237
  * @memberOf _.templateSettings
324
238
  * @type RegExp
325
239
  */
@@ -328,11 +242,27 @@
328
242
  /**
329
243
  * Used to reference the data object in the template text.
330
244
  *
331
- * @static
332
245
  * @memberOf _.templateSettings
333
246
  * @type String
334
247
  */
335
- 'variable': ''
248
+ 'variable': '',
249
+
250
+ /**
251
+ * Used to import variables into the compiled template.
252
+ *
253
+ * @memberOf _.templateSettings
254
+ * @type Object
255
+ */
256
+ 'imports': {
257
+
258
+ /**
259
+ * A reference to the `lodash` function.
260
+ *
261
+ * @memberOf _.templateSettings.imports
262
+ * @type Function
263
+ */
264
+ '_': lodash
265
+ }
336
266
  };
337
267
 
338
268
  /*--------------------------------------------------------------------------*/
@@ -344,134 +274,80 @@
344
274
  * @param {Obect} data The data object used to populate the text.
345
275
  * @returns {String} Returns the interpolated text.
346
276
  */
347
- var iteratorTemplate = template(
348
- // conditional strict mode
349
- "<% if (obj.useStrict) { %>'use strict';\n<% } %>" +
350
-
351
- // the `iteratee` may be reassigned by the `top` snippet
352
- 'var index, iteratee = <%= firstArg %>, ' +
353
- // assign the `result` variable an initial value
354
- 'result = <%= firstArg %>;\n' +
355
- // exit early if the first argument is falsey
356
- 'if (!<%= firstArg %>) return result;\n' +
357
- // add code before the iteration branches
358
- '<%= top %>;\n' +
359
-
360
- // array-like iteration:
361
- '<% if (arrayLoop) { %>' +
362
- 'var length = iteratee.length; index = -1;\n' +
363
- "if (typeof length == 'number') {" +
364
-
365
- // add support for accessing string characters by index if needed
366
- ' <% if (noCharByIndex) { %>\n' +
367
- ' if (isString(iteratee)) {\n' +
368
- " iteratee = iteratee.split('')\n" +
369
- ' }' +
370
- ' <% } %>\n' +
371
-
372
- // iterate over the array-like value
373
- ' while (++index < length) {\n' +
374
- ' <%= arrayLoop %>\n' +
375
- ' }\n' +
376
- '}\n' +
377
- 'else {' +
378
-
379
- // object iteration:
380
- // add support for iterating over `arguments` objects if needed
381
- ' <% } else if (nonEnumArgs) { %>\n' +
382
- ' var length = iteratee.length; index = -1;\n' +
383
- ' if (length && isArguments(iteratee)) {\n' +
384
- ' while (++index < length) {\n' +
385
- " index += '';\n" +
386
- ' <%= objectLoop %>\n' +
387
- ' }\n' +
388
- ' } else {' +
389
- ' <% } %>' +
390
-
391
- // Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1
392
- // (if the prototype or a property on the prototype has been set)
393
- // incorrectly sets a function's `prototype` property [[Enumerable]]
394
- // value to `true`. Because of this Lo-Dash standardizes on skipping
395
- // the the `prototype` property of functions regardless of its
396
- // [[Enumerable]] value.
397
- ' <% if (!hasDontEnumBug) { %>\n' +
398
- " var skipProto = typeof iteratee == 'function' && \n" +
399
- " propertyIsEnumerable.call(iteratee, 'prototype');\n" +
400
- ' <% } %>' +
401
-
402
- // iterate own properties using `Object.keys` if it's fast
403
- ' <% if (isKeysFast && useHas) { %>\n' +
404
- ' var ownIndex = -1,\n' +
405
- ' ownProps = objectTypes[typeof iteratee] ? nativeKeys(iteratee) : [],\n' +
406
- ' length = ownProps.length;\n\n' +
407
- ' while (++ownIndex < length) {\n' +
408
- ' index = ownProps[ownIndex];\n' +
409
- " <% if (!hasDontEnumBug) { %>if (!(skipProto && index == 'prototype')) {\n <% } %>" +
410
- ' <%= objectLoop %>\n' +
411
- ' <% if (!hasDontEnumBug) { %>}\n<% } %>' +
412
- ' }' +
413
-
414
- // else using a for-in loop
415
- ' <% } else { %>\n' +
416
- ' for (index in iteratee) {<%' +
417
- ' if (!hasDontEnumBug || useHas) { %>\n if (<%' +
418
- " if (!hasDontEnumBug) { %>!(skipProto && index == 'prototype')<% }" +
419
- ' if (!hasDontEnumBug && useHas) { %> && <% }' +
420
- ' if (useHas) { %>hasOwnProperty.call(iteratee, index)<% }' +
421
- ' %>) {' +
422
- ' <% } %>\n' +
423
- ' <%= objectLoop %>;' +
424
- ' <% if (!hasDontEnumBug || useHas) { %>\n }<% } %>\n' +
425
- ' }' +
426
- ' <% } %>' +
427
-
428
- // Because IE < 9 can't set the `[[Enumerable]]` attribute of an
429
- // existing property and the `constructor` property of a prototype
430
- // defaults to non-enumerable, Lo-Dash skips the `constructor`
431
- // property when it infers it's iterating over a `prototype` object.
432
- ' <% if (hasDontEnumBug) { %>\n\n' +
433
- ' var ctor = iteratee.constructor;\n' +
434
- ' <% for (var k = 0; k < 7; k++) { %>\n' +
435
- " index = '<%= shadowed[k] %>';\n" +
436
- ' if (<%' +
437
- " if (shadowed[k] == 'constructor') {" +
438
- ' %>!(ctor && ctor.prototype === iteratee) && <%' +
439
- ' } %>hasOwnProperty.call(iteratee, index)) {\n' +
440
- ' <%= objectLoop %>\n' +
441
- ' }' +
442
- ' <% } %>' +
443
- ' <% } %>' +
444
- ' <% if (arrayLoop || nonEnumArgs) { %>\n}<% } %>\n' +
445
-
446
- // add code to the bottom of the iteration function
447
- '<%= bottom %>;\n' +
448
- // finally, return the `result`
449
- 'return result'
450
- );
277
+ var iteratorTemplate = function(obj) {
278
+
279
+ var __p = 'var index, iterable = ' +
280
+ (obj.firstArg ) +
281
+ ', result = iterable;\nif (!iterable) return result;\n' +
282
+ (obj.top ) +
283
+ ';\n';
284
+ if (obj.arrays) {
285
+ __p += 'var length = iterable.length; index = -1;\nif (' +
286
+ (obj.arrays ) +
287
+ ') {\n while (++index < length) {\n ' +
288
+ (obj.loop ) +
289
+ '\n }\n}\nelse { ';
290
+ } ;
291
+
292
+ if (obj.isKeysFast && obj.useHas) {
293
+ __p += '\n var ownIndex = -1,\n ownProps = objectTypes[typeof iterable] ? nativeKeys(iterable) : [],\n length = ownProps.length;\n\n while (++ownIndex < length) {\n index = ownProps[ownIndex];\n ' +
294
+ (obj.loop ) +
295
+ '\n } ';
296
+ } else {
297
+ __p += '\n for (index in iterable) {';
298
+ if (obj.useHas) {
299
+ __p += '\n if (';
300
+ if (obj.useHas) {
301
+ __p += 'hasOwnProperty.call(iterable, index)';
302
+ } ;
303
+ __p += ') { ';
304
+ } ;
305
+ __p +=
306
+ (obj.loop ) +
307
+ '; ';
308
+ if (obj.useHas) {
309
+ __p += '\n }';
310
+ } ;
311
+ __p += '\n } ';
312
+ } ;
313
+
314
+ if (obj.arrays) {
315
+ __p += '\n}';
316
+ } ;
317
+ __p +=
318
+ (obj.bottom ) +
319
+ ';\nreturn result';
320
+
321
+
322
+ return __p
323
+ };
451
324
 
452
325
  /** Reusable iterator options for `assign` and `defaults` */
453
- var assignIteratorOptions = {
326
+ var defaultsIteratorOptions = {
454
327
  'args': 'object, source, guard',
455
328
  'top':
456
- "for (var argsIndex = 1, argsLength = typeof guard == 'number' ? 2 : arguments.length; argsIndex < argsLength; argsIndex++) {\n" +
457
- ' if ((iteratee = arguments[argsIndex])) {',
458
- 'objectLoop': 'result[index] = iteratee[index]',
329
+ 'var args = arguments,\n' +
330
+ ' argsIndex = 0,\n' +
331
+ " argsLength = typeof guard == 'number' ? 2 : args.length;\n" +
332
+ 'while (++argsIndex < argsLength) {\n' +
333
+ ' iterable = args[argsIndex];\n' +
334
+ ' if (iterable && objectTypes[typeof iterable]) {',
335
+ 'loop': "if (typeof result[index] == 'undefined') result[index] = iterable[index]",
459
336
  'bottom': ' }\n}'
460
337
  };
461
338
 
462
- /**
463
- * Reusable iterator options shared by `each`, `forIn`, and `forOwn`.
464
- */
339
+ /** Reusable iterator options shared by `each`, `forIn`, and `forOwn` */
465
340
  var eachIteratorOptions = {
466
341
  'args': 'collection, callback, thisArg',
467
342
  'top': "callback = callback && typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg)",
468
- 'arrayLoop': 'if (callback(iteratee[index], index, collection) === false) return result',
469
- 'objectLoop': 'if (callback(iteratee[index], index, collection) === false) return result'
343
+ 'arrays': "typeof length == 'number'",
344
+ 'loop': 'if (callback(iterable[index], index, collection) === false) return result'
470
345
  };
471
346
 
472
347
  /** Reusable iterator options for `forIn` and `forOwn` */
473
348
  var forOwnIteratorOptions = {
474
- 'arrayLoop': null
349
+ 'top': 'if (!objectTypes[typeof iterable]) return result;\n' + eachIteratorOptions.top,
350
+ 'arrays': false
475
351
  };
476
352
 
477
353
  /*--------------------------------------------------------------------------*/
@@ -485,7 +361,7 @@
485
361
  * @param {Mixed} value The value to search for.
486
362
  * @param {Number} [fromIndex=0] The index to search from.
487
363
  * @param {Number} [largeSize=30] The length at which an array is considered large.
488
- * @returns {Boolean} Returns `true` if `value` is found, else `false`.
364
+ * @returns {Boolean} Returns `true`, if `value` is found, else `false`.
489
365
  */
490
366
  function cachedContains(array, fromIndex, largeSize) {
491
367
  fromIndex || (fromIndex = 0);
@@ -555,17 +431,18 @@
555
431
  }
556
432
 
557
433
  /**
558
- * Creates a function that, when called, invokes `func` with the `this`
559
- * binding of `thisArg` and prepends any `partailArgs` to the arguments passed
560
- * to the bound function.
434
+ * Creates a function that, when called, invokes `func` with the `this` binding
435
+ * of `thisArg` and prepends any `partialArgs` to the arguments passed to the
436
+ * bound function.
561
437
  *
562
438
  * @private
563
439
  * @param {Function|String} func The function to bind or the method name.
564
440
  * @param {Mixed} [thisArg] The `this` binding of `func`.
565
441
  * @param {Array} partialArgs An array of arguments to be partially applied.
442
+ * @param {Object} [rightIndicator] Used to indicate partially applying arguments from the right.
566
443
  * @returns {Function} Returns the new bound function.
567
444
  */
568
- function createBound(func, thisArg, partialArgs) {
445
+ function createBound(func, thisArg, partialArgs, rightIndicator) {
569
446
  var isFunc = isFunction(func),
570
447
  isPartial = !partialArgs,
571
448
  key = thisArg;
@@ -589,7 +466,7 @@
589
466
  }
590
467
  if (partialArgs.length) {
591
468
  args = args.length
592
- ? partialArgs.concat(slice(args))
469
+ ? (args = slice(args), rightIndicator ? args.concat(partialArgs) : partialArgs.concat(args))
593
470
  : partialArgs;
594
471
  }
595
472
  if (this instanceof bound) {
@@ -609,28 +486,52 @@
609
486
  }
610
487
 
611
488
  /**
612
- * Produces an iteration callback bound to an optional `thisArg`. If `func` is
613
- * a property name, the callback will return the property value for a given element.
489
+ * Produces a callback bound to an optional `thisArg`. If `func` is a property
490
+ * name, the created callback will return the property value for a given element.
491
+ * If `func` is an object, the created callback will return `true` for elements
492
+ * that contain the equivalent object properties, otherwise it will return `false`.
614
493
  *
615
494
  * @private
616
- * @param {Function|String} [func=identity|property] The function called per
617
- * iteration or property name to query.
618
- * @param {Mixed} [thisArg] The `this` binding of `callback`.
619
- * @param {Object} [accumulating] Used to indicate that the callback should
620
- * accept an `accumulator` argument.
495
+ * @param {Mixed} [func=identity] The value to convert to a callback.
496
+ * @param {Mixed} [thisArg] The `this` binding of the created callback.
497
+ * @param {Number} [argCount=3] The number of arguments the callback accepts.
621
498
  * @returns {Function} Returns a callback function.
622
499
  */
623
- function createCallback(func, thisArg, accumulating) {
624
- if (!func) {
500
+ function createCallback(func, thisArg, argCount) {
501
+ if (func == null) {
625
502
  return identity;
626
503
  }
627
- if (typeof func != 'function') {
504
+ var type = typeof func;
505
+ if (type != 'function') {
506
+ if (type != 'object') {
507
+ return function(object) {
508
+ return object[func];
509
+ };
510
+ }
511
+ var props = keys(func);
628
512
  return function(object) {
629
- return object[func];
513
+ var length = props.length,
514
+ result = false;
515
+ while (length--) {
516
+ if (!(result = isEqual(object[props[length]], func[props[length]], indicatorObject))) {
517
+ break;
518
+ }
519
+ }
520
+ return result;
630
521
  };
631
522
  }
632
523
  if (typeof thisArg != 'undefined') {
633
- if (accumulating) {
524
+ if (argCount === 1) {
525
+ return function(value) {
526
+ return func.call(thisArg, value);
527
+ };
528
+ }
529
+ if (argCount === 2) {
530
+ return function(a, b) {
531
+ return func.call(thisArg, a, b);
532
+ };
533
+ }
534
+ if (argCount === 4) {
634
535
  return function(accumulator, value, index, object) {
635
536
  return func.call(thisArg, accumulator, value, index, object);
636
537
  };
@@ -647,25 +548,24 @@
647
548
  *
648
549
  * @private
649
550
  * @param {Object} [options1, options2, ...] The compile options object(s).
551
+ * arrays - A string of code to determine if the iterable is an array or array-like.
650
552
  * useHas - A boolean to specify using `hasOwnProperty` checks in the object loop.
651
553
  * args - A string of comma separated arguments the iteration function will accept.
652
554
  * top - A string of code to execute before the iteration branches.
653
- * arrayLoop - A string of code to execute in the array loop.
654
- * objectLoop - A string of code to execute in the object loop.
555
+ * loop - A string of code to execute in the object loop.
655
556
  * bottom - A string of code to execute after the iteration branches.
656
557
  *
657
558
  * @returns {Function} Returns the compiled function.
658
559
  */
659
560
  function createIterator() {
660
561
  var data = {
661
- 'arrayLoop': '',
662
- 'bottom': '',
663
- 'hasDontEnumBug': hasDontEnumBug,
562
+ // support properties
664
563
  'isKeysFast': isKeysFast,
665
- 'objectLoop': '',
666
- 'nonEnumArgs': nonEnumArgs,
667
- 'noCharByIndex': noCharByIndex,
668
- 'shadowed': shadowed,
564
+
565
+ // iterator options
566
+ 'arrays': 'isArray(iterable)',
567
+ 'bottom': '',
568
+ 'loop': '',
669
569
  'top': '',
670
570
  'useHas': true
671
571
  };
@@ -681,14 +581,14 @@
681
581
 
682
582
  // create the function factory
683
583
  var factory = Function(
684
- 'createCallback, hasOwnProperty, isArguments, isString, objectTypes, ' +
685
- 'nativeKeys, propertyIsEnumerable',
584
+ 'createCallback, hasOwnProperty, isArguments, isArray, isString, ' +
585
+ 'objectTypes, nativeKeys',
686
586
  'return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}'
687
587
  );
688
588
  // return the compiled function
689
589
  return factory(
690
- createCallback, hasOwnProperty, isArguments, isString, objectTypes,
691
- nativeKeys, propertyIsEnumerable
590
+ createCallback, hasOwnProperty, isArguments, isArray, isString,
591
+ objectTypes, nativeKeys
692
592
  );
693
593
  }
694
594
 
@@ -700,6 +600,7 @@
700
600
  * iteration early by explicitly returning `false`.
701
601
  *
702
602
  * @private
603
+ * @type Function
703
604
  * @param {Array|Object|String} collection The collection to iterate over.
704
605
  * @param {Function} [callback=identity] The function called per iteration.
705
606
  * @param {Mixed} [thisArg] The `this` binding of `callback`.
@@ -793,25 +694,6 @@
793
694
 
794
695
  /*--------------------------------------------------------------------------*/
795
696
 
796
- /**
797
- * Assigns own enumerable properties of source object(s) to the `destination`
798
- * object. Subsequent sources will overwrite propery assignments of previous
799
- * sources.
800
- *
801
- * @static
802
- * @memberOf _
803
- * @alias extend
804
- * @category Objects
805
- * @param {Object} object The destination object.
806
- * @param {Object} [source1, source2, ...] The source objects.
807
- * @returns {Object} Returns the destination object.
808
- * @example
809
- *
810
- * _.assign({ 'name': 'moe' }, { 'age': 40 });
811
- * // => { 'name': 'moe', 'age': 40 }
812
- */
813
- var assign = createIterator(assignIteratorOptions);
814
-
815
697
  /**
816
698
  * Checks if `value` is an `arguments` object.
817
699
  *
@@ -819,7 +701,7 @@
819
701
  * @memberOf _
820
702
  * @category Objects
821
703
  * @param {Mixed} value The value to check.
822
- * @returns {Boolean} Returns `true` if the `value` is an `arguments` object, else `false`.
704
+ * @returns {Boolean} Returns `true`, if the `value` is an `arguments` object, else `false`.
823
705
  * @example
824
706
  *
825
707
  * (function() { return _.isArguments(arguments); })(1, 2, 3);
@@ -831,12 +713,6 @@
831
713
  function isArguments(value) {
832
714
  return toString.call(value) == argsClass;
833
715
  }
834
- // fallback for browsers that can't detect `arguments` objects by [[Class]]
835
- if (noArgsClass) {
836
- isArguments = function(value) {
837
- return value ? hasOwnProperty.call(value, 'callee') : false;
838
- };
839
- }
840
716
 
841
717
  /**
842
718
  * Iterates over `object`'s own and inherited enumerable properties, executing
@@ -846,6 +722,7 @@
846
722
  *
847
723
  * @static
848
724
  * @memberOf _
725
+ * @type Function
849
726
  * @category Objects
850
727
  * @param {Object} object The object to iterate over.
851
728
  * @param {Function} [callback=identity] The function called per iteration.
@@ -878,6 +755,7 @@
878
755
  *
879
756
  * @static
880
757
  * @memberOf _
758
+ * @type Function
881
759
  * @category Objects
882
760
  * @param {Object} object The object to iterate over.
883
761
  * @param {Function} [callback=identity] The function called per iteration.
@@ -892,6 +770,48 @@
892
770
  */
893
771
  var forOwn = createIterator(eachIteratorOptions, forOwnIteratorOptions);
894
772
 
773
+ /**
774
+ * Checks if `value` is an array.
775
+ *
776
+ * @static
777
+ * @memberOf _
778
+ * @category Objects
779
+ * @param {Mixed} value The value to check.
780
+ * @returns {Boolean} Returns `true`, if the `value` is an array, else `false`.
781
+ * @example
782
+ *
783
+ * (function() { return _.isArray(arguments); })();
784
+ * // => false
785
+ *
786
+ * _.isArray([1, 2, 3]);
787
+ * // => true
788
+ */
789
+ var isArray = nativeIsArray || function(value) {
790
+ // `instanceof` may cause a memory leak in IE 7 if `value` is a host object
791
+ // http://ajaxian.com/archives/working-aroung-the-instanceof-memory-leak
792
+ return value instanceof Array || toString.call(value) == arrayClass;
793
+ };
794
+
795
+ /**
796
+ * Creates an array composed of the own enumerable property names of `object`.
797
+ *
798
+ * @static
799
+ * @memberOf _
800
+ * @category Objects
801
+ * @param {Object} object The object to inspect.
802
+ * @returns {Array} Returns a new array of property names.
803
+ * @example
804
+ *
805
+ * _.keys({ 'one': 1, 'two': 2, 'three': 3 });
806
+ * // => ['one', 'two', 'three'] (order is not guaranteed)
807
+ */
808
+ var keys = !nativeKeys ? shimKeys : function(object) {
809
+ if (!isObject(object)) {
810
+ return [];
811
+ }
812
+ return nativeKeys(object);
813
+ };
814
+
895
815
  /**
896
816
  * A fallback implementation of `isPlainObject` that checks if a given `value`
897
817
  * is an object created by the `Object` constructor, assuming objects created
@@ -900,7 +820,7 @@
900
820
  *
901
821
  * @private
902
822
  * @param {Mixed} value The value to check.
903
- * @returns {Boolean} Returns `true` if `value` is a plain object, else `false`.
823
+ * @returns {Boolean} Returns `true`, if `value` is a plain object, else `false`.
904
824
  */
905
825
  function shimIsPlainObject(value) {
906
826
  // avoid non-objects and false positives for `arguments` objects
@@ -910,17 +830,7 @@
910
830
  }
911
831
  // check that the constructor is `Object` (i.e. `Object instanceof Object`)
912
832
  var ctor = value.constructor;
913
- if ((!isFunction(ctor) && (!noNodeClass || !isNode(value))) || ctor instanceof ctor) {
914
- // IE < 9 iterates inherited properties before own properties. If the first
915
- // iterated property is an object's own property then there are no inherited
916
- // enumerable properties.
917
- if (iteratesOwnLast) {
918
- forIn(value, function(value, key, object) {
919
- result = !hasOwnProperty.call(object, key);
920
- return false;
921
- });
922
- return result === false;
923
- }
833
+ if ((!isFunction(ctor)) || ctor instanceof ctor) {
924
834
  // In most environments an object's own properties are iterated before
925
835
  // its inherited properties. If the last iterated property is an object's
926
836
  // own property then there are no inherited enumerable properties.
@@ -961,7 +871,7 @@
961
871
  '<': '&lt;',
962
872
  '>': '&gt;',
963
873
  '"': '&quot;',
964
- "'": '&#x27;'
874
+ "'": '&#39;'
965
875
  };
966
876
 
967
877
  /** Used to convert HTML entities to characters */
@@ -969,27 +879,71 @@
969
879
 
970
880
  /*--------------------------------------------------------------------------*/
971
881
 
882
+ /**
883
+ * Assigns own enumerable properties of source object(s) to the destination
884
+ * object. Subsequent sources will overwrite propery assignments of previous
885
+ * sources. If a `callback` function is passed, it will be executed to produce
886
+ * the assigned values. The `callback` is bound to `thisArg` and invoked with
887
+ * two arguments; (objectValue, sourceValue).
888
+ *
889
+ * @static
890
+ * @memberOf _
891
+ * @type Function
892
+ * @alias extend
893
+ * @category Objects
894
+ * @param {Object} object The destination object.
895
+ * @param {Object} [source1, source2, ...] The source objects.
896
+ * @param {Function} [callback] The function to customize assigning values.
897
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
898
+ * @returns {Object} Returns the destination object.
899
+ * @example
900
+ *
901
+ * _.assign({ 'name': 'moe' }, { 'age': 40 });
902
+ * // => { 'name': 'moe', 'age': 40 }
903
+ *
904
+ * var defaults = _.partialRight(_.assign, function(a, b) {
905
+ * return typeof a == 'undefined' ? b : a;
906
+ * });
907
+ *
908
+ * var food = { 'name': 'apple' };
909
+ * defaults(food, { 'name': 'banana', 'type': 'fruit' });
910
+ * // => { 'name': 'apple', 'type': 'fruit' }
911
+ */
912
+ var assign = createIterator(defaultsIteratorOptions, {
913
+ 'top':
914
+ defaultsIteratorOptions.top.replace(';',
915
+ ';\n' +
916
+ "if (argsLength > 3 && typeof args[argsLength - 2] == 'function') {\n" +
917
+ ' var callback = createCallback(args[--argsLength - 1], args[argsLength--], 2);\n' +
918
+ "} else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {\n" +
919
+ ' callback = args[--argsLength];\n' +
920
+ '}'
921
+ ),
922
+ 'loop': 'result[index] = callback ? callback(result[index], iterable[index]) : iterable[index]'
923
+ });
924
+
972
925
  /**
973
926
  * Creates a clone of `value`. If `deep` is `true`, nested objects will also
974
- * be cloned, otherwise they will be assigned by reference.
927
+ * be cloned, otherwise they will be assigned by reference. If a `callback`
928
+ * function is passed, it will be executed to produce the cloned values. If
929
+ * `callback` returns `undefined`, cloning will be handled by the method instead.
930
+ * The `callback` is bound to `thisArg` and invoked with one argument; (value).
975
931
  *
976
932
  * @static
977
933
  * @memberOf _
978
934
  * @category Objects
979
935
  * @param {Mixed} value The value to clone.
980
- * @param {Boolean} deep A flag to indicate a deep clone.
981
- * @param- {Object} [guard] Internally used to allow this method to work with
982
- * others like `_.map` without using their callback `index` argument for `deep`.
936
+ * @param {Boolean} [deep=false] A flag to indicate a deep clone.
937
+ * @param {Function} [callback] The function to customize cloning values.
938
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
983
939
  * @param- {Array} [stackA=[]] Internally used to track traversed source objects.
984
- * @param- {Array} [stackB=[]] Internally used to associate clones with their
985
- * source counterparts.
940
+ * @param- {Array} [stackB=[]] Internally used to associate clones with source counterparts.
986
941
  * @returns {Mixed} Returns the cloned `value`.
987
942
  * @example
988
943
  *
989
944
  * var stooges = [
990
945
  * { 'name': 'moe', 'age': 40 },
991
- * { 'name': 'larry', 'age': 50 },
992
- * { 'name': 'curly', 'age': 60 }
946
+ * { 'name': 'larry', 'age': 50 }
993
947
  * ];
994
948
  *
995
949
  * var shallow = _.clone(stooges);
@@ -999,41 +953,63 @@
999
953
  * var deep = _.clone(stooges, true);
1000
954
  * deep[0] === stooges[0];
1001
955
  * // => false
956
+ *
957
+ * _.mixin({
958
+ * 'clone': _.partialRight(_.clone, function(value) {
959
+ * return _.isElement(value) ? value.cloneNode(false) : undefined;
960
+ * })
961
+ * });
962
+ *
963
+ * var clone = _.clone(document.body);
964
+ * clone.childNodes.length;
965
+ * // => 0
1002
966
  */
1003
- function clone(value, deep, guard, stackA, stackB) {
1004
- if (value == null) {
1005
- return value;
1006
- }
1007
- if (guard) {
967
+ function clone(value, deep, callback, thisArg, stackA, stackB) {
968
+ var result = value;
969
+
970
+ // allows working with "Collections" methods without using their `callback`
971
+ // argument, `index|key`, for this method's `callback`
972
+ if (typeof deep == 'function') {
973
+ thisArg = callback;
974
+ callback = deep;
1008
975
  deep = false;
1009
976
  }
977
+ if (typeof callback == 'function') {
978
+ callback = typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg, 1);
979
+ result = callback(result);
980
+
981
+ var done = typeof result != 'undefined';
982
+ if (!done) {
983
+ result = value;
984
+ }
985
+ }
1010
986
  // inspect [[Class]]
1011
- var isObj = isObject(value);
987
+ var isObj = isObject(result);
1012
988
  if (isObj) {
1013
- var className = toString.call(value);
1014
- if (!cloneableClasses[className] || (noNodeClass && isNode(value))) {
1015
- return value;
989
+ var className = toString.call(result);
990
+ if (!cloneableClasses[className]) {
991
+ return result;
1016
992
  }
1017
- var isArr = isArray(value);
993
+ var isArr = isArray(result);
1018
994
  }
1019
995
  // shallow clone
1020
996
  if (!isObj || !deep) {
1021
- return isObj
1022
- ? (isArr ? slice(value) : assign({}, value))
1023
- : value;
997
+ return isObj && !done
998
+ ? (isArr ? slice(result) : assign({}, result))
999
+ : result;
1024
1000
  }
1025
1001
  var ctor = ctorByClass[className];
1026
1002
  switch (className) {
1027
1003
  case boolClass:
1028
1004
  case dateClass:
1029
- return new ctor(+value);
1005
+ return done ? result : new ctor(+result);
1030
1006
 
1031
1007
  case numberClass:
1032
1008
  case stringClass:
1033
- return new ctor(value);
1009
+ return done ? result : new ctor(result);
1034
1010
 
1035
1011
  case regexpClass:
1036
- return ctor(value.source, reFlags.exec(value));
1012
+ return done ? result : ctor(result.source, reFlags.exec(result));
1037
1013
  }
1038
1014
  // check for circular references and return corresponding clone
1039
1015
  stackA || (stackA = []);
@@ -1046,80 +1022,98 @@
1046
1022
  }
1047
1023
  }
1048
1024
  // init cloned object
1049
- var result = isArr ? ctor(value.length) : {};
1025
+ if (!done) {
1026
+ result = isArr ? ctor(result.length) : {};
1050
1027
 
1028
+ // add array properties assigned by `RegExp#exec`
1029
+ if (isArr) {
1030
+ if (hasOwnProperty.call(value, 'index')) {
1031
+ result.index = value.index;
1032
+ }
1033
+ if (hasOwnProperty.call(value, 'input')) {
1034
+ result.input = value.input;
1035
+ }
1036
+ }
1037
+ }
1051
1038
  // add the source value to the stack of traversed objects
1052
1039
  // and associate it with its clone
1053
1040
  stackA.push(value);
1054
1041
  stackB.push(result);
1055
1042
 
1056
1043
  // recursively populate clone (susceptible to call stack limits)
1057
- (isArr ? forEach : forOwn)(value, function(objValue, key) {
1058
- result[key] = clone(objValue, deep, null, stackA, stackB);
1044
+ (isArr ? forEach : forOwn)(done ? result : value, function(objValue, key) {
1045
+ result[key] = clone(objValue, deep, callback, undefined, stackA, stackB);
1059
1046
  });
1060
1047
 
1061
- // add array properties assigned by `RegExp#exec`
1062
- if (isArr) {
1063
- if (hasOwnProperty.call(value, 'index')) {
1064
- result.index = value.index;
1065
- }
1066
- if (hasOwnProperty.call(value, 'input')) {
1067
- result.input = value.input;
1068
- }
1069
- }
1070
1048
  return result;
1071
1049
  }
1072
1050
 
1073
1051
  /**
1074
- * Creates a deep clone of `value`. Functions and DOM nodes are **not** cloned.
1075
- * The enumerable properties of `arguments` objects and objects created by
1076
- * constructors other than `Object` are cloned to plain `Object` objects.
1052
+ * Creates a deep clone of `value`. If a `callback` function is passed, it will
1053
+ * be executed to produce the cloned values. If `callback` returns the value it
1054
+ * was passed, cloning will be handled by the method instead. The `callback` is
1055
+ * bound to `thisArg` and invoked with one argument; (value).
1077
1056
  *
1078
- * Note: This function is loosely based on the structured clone algorithm.
1079
- * See http://www.w3.org/TR/html5/common-dom-interfaces.html#internal-structured-cloning-algorithm.
1057
+ * Note: This function is loosely based on the structured clone algorithm. Functions
1058
+ * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and
1059
+ * objects created by constructors other than `Object` are cloned to plain `Object` objects.
1060
+ * See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm.
1080
1061
  *
1081
1062
  * @static
1082
1063
  * @memberOf _
1083
1064
  * @category Objects
1084
1065
  * @param {Mixed} value The value to deep clone.
1066
+ * @param {Function} [callback] The function to customize cloning values.
1067
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
1085
1068
  * @returns {Mixed} Returns the deep cloned `value`.
1086
1069
  * @example
1087
1070
  *
1088
1071
  * var stooges = [
1089
1072
  * { 'name': 'moe', 'age': 40 },
1090
- * { 'name': 'larry', 'age': 50 },
1091
- * { 'name': 'curly', 'age': 60 }
1073
+ * { 'name': 'larry', 'age': 50 }
1092
1074
  * ];
1093
1075
  *
1094
1076
  * var deep = _.cloneDeep(stooges);
1095
1077
  * deep[0] === stooges[0];
1096
1078
  * // => false
1079
+ *
1080
+ * var view = {
1081
+ * 'label': 'docs',
1082
+ * 'node': element
1083
+ * };
1084
+ *
1085
+ * var clone = _.cloneDeep(view, function(value) {
1086
+ * return _.isElement(value) ? value.cloneNode(true) : value;
1087
+ * });
1088
+ *
1089
+ * clone.node == view.node;
1090
+ * // => false
1097
1091
  */
1098
- function cloneDeep(value) {
1099
- return clone(value, true);
1092
+ function cloneDeep(value, callback, thisArg) {
1093
+ return clone(value, true, callback, thisArg);
1100
1094
  }
1101
1095
 
1102
1096
  /**
1103
- * Assigns own enumerable properties of source object(s) to the `destination`
1104
- * object for all `destination` properties that resolve to `null`/`undefined`.
1105
- * Once a property is set, additional defaults of the same property will be
1106
- * ignored.
1097
+ * Assigns own enumerable properties of source object(s) to the destination
1098
+ * object for all destination properties that resolve to `undefined`. Once a
1099
+ * property is set, additional defaults of the same property will be ignored.
1107
1100
  *
1108
1101
  * @static
1109
1102
  * @memberOf _
1103
+ * @type Function
1110
1104
  * @category Objects
1111
1105
  * @param {Object} object The destination object.
1112
- * @param {Object} [default1, default2, ...] The default objects.
1106
+ * @param {Object} [source1, source2, ...] The source objects.
1107
+ * @param- {Object} [guard] Internally used to allow working with `_.reduce`
1108
+ * without using its callback's `key` and `object` arguments as sources.
1113
1109
  * @returns {Object} Returns the destination object.
1114
1110
  * @example
1115
1111
  *
1116
- * var iceCream = { 'flavor': 'chocolate' };
1117
- * _.defaults(iceCream, { 'flavor': 'vanilla', 'sprinkles': 'rainbow' });
1118
- * // => { 'flavor': 'chocolate', 'sprinkles': 'rainbow' }
1112
+ * var food = { 'name': 'apple' };
1113
+ * _.defaults(food, { 'name': 'banana', 'type': 'fruit' });
1114
+ * // => { 'name': 'apple', 'type': 'fruit' }
1119
1115
  */
1120
- var defaults = createIterator(assignIteratorOptions, {
1121
- 'objectLoop': 'if (result[index] == null) ' + assignIteratorOptions.objectLoop
1122
- });
1116
+ var defaults = createIterator(defaultsIteratorOptions);
1123
1117
 
1124
1118
  /**
1125
1119
  * Creates a sorted array of all enumerable properties, own and inherited,
@@ -1175,47 +1169,30 @@
1175
1169
  * @returns {Object} Returns the created inverted object.
1176
1170
  * @example
1177
1171
  *
1178
- * _.invert({ 'first': 'Moe', 'second': 'Larry', 'third': 'Curly' });
1179
- * // => { 'Moe': 'first', 'Larry': 'second', 'Curly': 'third' } (order is not guaranteed)
1172
+ * _.invert({ 'first': 'moe', 'second': 'larry' });
1173
+ * // => { 'moe': 'first', 'larry': 'second' } (order is not guaranteed)
1180
1174
  */
1181
1175
  function invert(object) {
1182
- var result = {};
1183
- forOwn(object, function(value, key) {
1184
- result[value] = key;
1185
- });
1176
+ var index = -1,
1177
+ props = keys(object),
1178
+ length = props.length,
1179
+ result = {};
1180
+
1181
+ while (++index < length) {
1182
+ var key = props[index];
1183
+ result[object[key]] = key;
1184
+ }
1186
1185
  return result;
1187
1186
  }
1188
1187
 
1189
1188
  /**
1190
- * Checks if `value` is an array.
1191
- *
1192
- * @static
1193
- * @memberOf _
1194
- * @category Objects
1195
- * @param {Mixed} value The value to check.
1196
- * @returns {Boolean} Returns `true` if the `value` is an array, else `false`.
1197
- * @example
1198
- *
1199
- * (function() { return _.isArray(arguments); })();
1200
- * // => false
1201
- *
1202
- * _.isArray([1, 2, 3]);
1203
- * // => true
1204
- */
1205
- var isArray = nativeIsArray || function(value) {
1206
- // `instanceof` may cause a memory leak in IE 7 if `value` is a host object
1207
- // http://ajaxian.com/archives/working-aroung-the-instanceof-memory-leak
1208
- return (argsAreObjects && value instanceof Array) || toString.call(value) == arrayClass;
1209
- };
1210
-
1211
- /**
1212
- * Checks if `value` is a boolean (`true` or `false`) value.
1189
+ * Checks if `value` is a boolean value.
1213
1190
  *
1214
1191
  * @static
1215
1192
  * @memberOf _
1216
1193
  * @category Objects
1217
1194
  * @param {Mixed} value The value to check.
1218
- * @returns {Boolean} Returns `true` if the `value` is a boolean value, else `false`.
1195
+ * @returns {Boolean} Returns `true`, if the `value` is a boolean value, else `false`.
1219
1196
  * @example
1220
1197
  *
1221
1198
  * _.isBoolean(null);
@@ -1232,7 +1209,7 @@
1232
1209
  * @memberOf _
1233
1210
  * @category Objects
1234
1211
  * @param {Mixed} value The value to check.
1235
- * @returns {Boolean} Returns `true` if the `value` is a date, else `false`.
1212
+ * @returns {Boolean} Returns `true`, if the `value` is a date, else `false`.
1236
1213
  * @example
1237
1214
  *
1238
1215
  * _.isDate(new Date);
@@ -1249,7 +1226,7 @@
1249
1226
  * @memberOf _
1250
1227
  * @category Objects
1251
1228
  * @param {Mixed} value The value to check.
1252
- * @returns {Boolean} Returns `true` if the `value` is a DOM element, else `false`.
1229
+ * @returns {Boolean} Returns `true`, if the `value` is a DOM element, else `false`.
1253
1230
  * @example
1254
1231
  *
1255
1232
  * _.isElement(document.body);
@@ -1268,7 +1245,7 @@
1268
1245
  * @memberOf _
1269
1246
  * @category Objects
1270
1247
  * @param {Array|Object|String} value The value to inspect.
1271
- * @returns {Boolean} Returns `true` if the `value` is empty, else `false`.
1248
+ * @returns {Boolean} Returns `true`, if the `value` is empty, else `false`.
1272
1249
  * @example
1273
1250
  *
1274
1251
  * _.isEmpty([1, 2, 3]);
@@ -1289,7 +1266,7 @@
1289
1266
  length = value.length;
1290
1267
 
1291
1268
  if ((className == arrayClass || className == stringClass ||
1292
- className == argsClass || (noArgsClass && isArguments(value))) ||
1269
+ className == argsClass) ||
1293
1270
  (className == objectClass && typeof length == 'number' && isFunction(value.splice))) {
1294
1271
  return !length;
1295
1272
  }
@@ -1301,48 +1278,84 @@
1301
1278
 
1302
1279
  /**
1303
1280
  * Performs a deep comparison between two values to determine if they are
1304
- * equivalent to each other.
1281
+ * equivalent to each other. If `callback` is passed, it will be executed to
1282
+ * compare values. If `callback` returns `undefined`, comparisons will be handled
1283
+ * by the method instead. The `callback` is bound to `thisArg` and invoked with
1284
+ * two arguments; (a, b).
1305
1285
  *
1306
1286
  * @static
1307
1287
  * @memberOf _
1308
1288
  * @category Objects
1309
1289
  * @param {Mixed} a The value to compare.
1310
1290
  * @param {Mixed} b The other value to compare.
1291
+ * @param {Function} [callback] The function to customize comparing values.
1292
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
1311
1293
  * @param- {Object} [stackA=[]] Internally used track traversed `a` objects.
1312
1294
  * @param- {Object} [stackB=[]] Internally used track traversed `b` objects.
1313
- * @returns {Boolean} Returns `true` if the values are equvalent, else `false`.
1295
+ * @returns {Boolean} Returns `true`, if the values are equvalent, else `false`.
1314
1296
  * @example
1315
1297
  *
1316
- * var moe = { 'name': 'moe', 'luckyNumbers': [13, 27, 34] };
1317
- * var clone = { 'name': 'moe', 'luckyNumbers': [13, 27, 34] };
1298
+ * var moe = { 'name': 'moe', 'age': 40 };
1299
+ * var copy = { 'name': 'moe', 'age': 40 };
1318
1300
  *
1319
- * moe == clone;
1301
+ * moe == copy;
1320
1302
  * // => false
1321
1303
  *
1322
- * _.isEqual(moe, clone);
1304
+ * _.isEqual(moe, copy);
1305
+ * // => true
1306
+ *
1307
+ * var words = ['hello', 'goodbye'];
1308
+ * var otherWords = ['hi', 'goodbye'];
1309
+ *
1310
+ * _.isEqual(words, otherWords, function(a, b) {
1311
+ * var reGreet = /^(?:hello|hi)$/i,
1312
+ * aGreet = _.isString(a) && reGreet.test(a),
1313
+ * bGreet = _.isString(b) && reGreet.test(b);
1314
+ *
1315
+ * return (aGreet || bGreet) ? (aGreet == bGreet) : undefined;
1316
+ * });
1323
1317
  * // => true
1324
1318
  */
1325
- function isEqual(a, b, stackA, stackB) {
1319
+ function isEqual(a, b, callback, thisArg, stackA, stackB) {
1320
+ // used to indicate that when comparing objects, `a` has at least the properties of `b`
1321
+ var whereIndicator = callback === indicatorObject;
1322
+ if (callback && !whereIndicator) {
1323
+ callback = typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg, 2);
1324
+ var result = callback(a, b);
1325
+ if (typeof result != 'undefined') {
1326
+ return !!result;
1327
+ }
1328
+ }
1326
1329
  // exit early for identical values
1327
1330
  if (a === b) {
1328
1331
  // treat `+0` vs. `-0` as not equal
1329
1332
  return a !== 0 || (1 / a == 1 / b);
1330
1333
  }
1331
- // a strict comparison is necessary because `null == undefined`
1334
+ var type = typeof a,
1335
+ otherType = typeof b;
1336
+
1337
+ // exit early for unlike primitive values
1338
+ if (a === a &&
1339
+ (!a || (type != 'function' && type != 'object')) &&
1340
+ (!b || (otherType != 'function' && otherType != 'object'))) {
1341
+ return false;
1342
+ }
1343
+ // exit early for `null` and `undefined`, avoiding ES3's Function#call behavior
1344
+ // http://es5.github.com/#x15.3.4.4
1332
1345
  if (a == null || b == null) {
1333
1346
  return a === b;
1334
1347
  }
1335
1348
  // compare [[Class]] names
1336
1349
  var className = toString.call(a),
1337
- otherName = toString.call(b);
1350
+ otherClass = toString.call(b);
1338
1351
 
1339
1352
  if (className == argsClass) {
1340
1353
  className = objectClass;
1341
1354
  }
1342
- if (otherName == argsClass) {
1343
- otherName = objectClass;
1355
+ if (otherClass == argsClass) {
1356
+ otherClass = objectClass;
1344
1357
  }
1345
- if (className != otherName) {
1358
+ if (className != otherClass) {
1346
1359
  return false;
1347
1360
  }
1348
1361
  switch (className) {
@@ -1369,15 +1382,15 @@
1369
1382
  if (!isArr) {
1370
1383
  // unwrap any `lodash` wrapped values
1371
1384
  if (a.__wrapped__ || b.__wrapped__) {
1372
- return isEqual(a.__wrapped__ || a, b.__wrapped__ || b);
1385
+ return isEqual(a.__wrapped__ || a, b.__wrapped__ || b, callback, thisArg, stackA, stackB);
1373
1386
  }
1374
1387
  // exit for functions and DOM nodes
1375
- if (className != objectClass || (noNodeClass && (isNode(a) || isNode(b)))) {
1388
+ if (className != objectClass) {
1376
1389
  return false;
1377
1390
  }
1378
1391
  // in older versions of Opera, `arguments` objects have `Array` constructors
1379
- var ctorA = !argsAreObjects && isArguments(a) ? Object : a.constructor,
1380
- ctorB = !argsAreObjects && isArguments(b) ? Object : b.constructor;
1392
+ var ctorA = a.constructor,
1393
+ ctorB = b.constructor;
1381
1394
 
1382
1395
  // non `Object` object instances with different constructors are not equal
1383
1396
  if (ctorA != ctorB && !(
@@ -1399,9 +1412,8 @@
1399
1412
  return stackB[length] == b;
1400
1413
  }
1401
1414
  }
1402
- var index = -1,
1403
- result = true,
1404
- size = 0;
1415
+ var size = 0;
1416
+ result = true;
1405
1417
 
1406
1418
  // add `a` and `b` to the stack of traversed objects
1407
1419
  stackA.push(a);
@@ -1409,36 +1421,47 @@
1409
1421
 
1410
1422
  // recursively compare objects and arrays (susceptible to call stack limits)
1411
1423
  if (isArr) {
1412
- // compare lengths to determine if a deep comparison is necessary
1413
- size = a.length;
1414
- result = size == b.length;
1424
+ length = a.length;
1425
+ size = b.length;
1415
1426
 
1416
- if (result) {
1417
- // deep compare the contents, ignoring non-numeric properties
1418
- while (size--) {
1419
- if (!(result = isEqual(a[size], b[size], stackA, stackB))) {
1420
- break;
1427
+ // compare lengths to determine if a deep comparison is necessary
1428
+ result = size == a.length;
1429
+ if (!result && !whereIndicator) {
1430
+ return result;
1431
+ }
1432
+ // deep compare the contents, ignoring non-numeric properties
1433
+ while (size--) {
1434
+ var index = length,
1435
+ value = b[size];
1436
+
1437
+ if (whereIndicator) {
1438
+ while (index--) {
1439
+ if ((result = isEqual(a[index], value, callback, thisArg, stackA, stackB))) {
1440
+ break;
1441
+ }
1421
1442
  }
1443
+ } else if (!(result = isEqual(a[size], value, callback, thisArg, stackA, stackB))) {
1444
+ break;
1422
1445
  }
1423
1446
  }
1424
1447
  return result;
1425
1448
  }
1426
1449
  // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys`
1427
1450
  // which, in this case, is more costly
1428
- forIn(a, function(value, key, a) {
1429
- if (hasOwnProperty.call(a, key)) {
1451
+ forIn(b, function(value, key, b) {
1452
+ if (hasOwnProperty.call(b, key)) {
1430
1453
  // count the number of properties.
1431
1454
  size++;
1432
1455
  // deep compare each property value.
1433
- return (result = hasOwnProperty.call(b, key) && isEqual(value, b[key], stackA, stackB));
1456
+ return (result = hasOwnProperty.call(a, key) && isEqual(a[key], value, callback, thisArg, stackA, stackB));
1434
1457
  }
1435
1458
  });
1436
1459
 
1437
- if (result) {
1460
+ if (result && !whereIndicator) {
1438
1461
  // ensure both objects have the same number of properties
1439
- forIn(b, function(value, key, b) {
1440
- if (hasOwnProperty.call(b, key)) {
1441
- // `size` will be `-1` if `b` has more properties than `a`
1462
+ forIn(a, function(value, key, a) {
1463
+ if (hasOwnProperty.call(a, key)) {
1464
+ // `size` will be `-1` if `a` has more properties than `b`
1442
1465
  return (result = --size > -1);
1443
1466
  }
1444
1467
  });
@@ -1456,7 +1479,7 @@
1456
1479
  * @memberOf _
1457
1480
  * @category Objects
1458
1481
  * @param {Mixed} value The value to check.
1459
- * @returns {Boolean} Returns `true` if the `value` is a finite number, else `false`.
1482
+ * @returns {Boolean} Returns `true`, if the `value` is finite, else `false`.
1460
1483
  * @example
1461
1484
  *
1462
1485
  * _.isFinite(-101);
@@ -1485,7 +1508,7 @@
1485
1508
  * @memberOf _
1486
1509
  * @category Objects
1487
1510
  * @param {Mixed} value The value to check.
1488
- * @returns {Boolean} Returns `true` if the `value` is a function, else `false`.
1511
+ * @returns {Boolean} Returns `true`, if the `value` is a function, else `false`.
1489
1512
  * @example
1490
1513
  *
1491
1514
  * _.isFunction(_);
@@ -1509,7 +1532,7 @@
1509
1532
  * @memberOf _
1510
1533
  * @category Objects
1511
1534
  * @param {Mixed} value The value to check.
1512
- * @returns {Boolean} Returns `true` if the `value` is an object, else `false`.
1535
+ * @returns {Boolean} Returns `true`, if the `value` is an object, else `false`.
1513
1536
  * @example
1514
1537
  *
1515
1538
  * _.isObject({});
@@ -1539,7 +1562,7 @@
1539
1562
  * @memberOf _
1540
1563
  * @category Objects
1541
1564
  * @param {Mixed} value The value to check.
1542
- * @returns {Boolean} Returns `true` if the `value` is `NaN`, else `false`.
1565
+ * @returns {Boolean} Returns `true`, if the `value` is `NaN`, else `false`.
1543
1566
  * @example
1544
1567
  *
1545
1568
  * _.isNaN(NaN);
@@ -1567,7 +1590,7 @@
1567
1590
  * @memberOf _
1568
1591
  * @category Objects
1569
1592
  * @param {Mixed} value The value to check.
1570
- * @returns {Boolean} Returns `true` if the `value` is `null`, else `false`.
1593
+ * @returns {Boolean} Returns `true`, if the `value` is `null`, else `false`.
1571
1594
  * @example
1572
1595
  *
1573
1596
  * _.isNull(null);
@@ -1587,7 +1610,7 @@
1587
1610
  * @memberOf _
1588
1611
  * @category Objects
1589
1612
  * @param {Mixed} value The value to check.
1590
- * @returns {Boolean} Returns `true` if the `value` is a number, else `false`.
1613
+ * @returns {Boolean} Returns `true`, if the `value` is a number, else `false`.
1591
1614
  * @example
1592
1615
  *
1593
1616
  * _.isNumber(8.4 * 5);
@@ -1604,7 +1627,7 @@
1604
1627
  * @memberOf _
1605
1628
  * @category Objects
1606
1629
  * @param {Mixed} value The value to check.
1607
- * @returns {Boolean} Returns `true` if `value` is a plain object, else `false`.
1630
+ * @returns {Boolean} Returns `true`, if `value` is a plain object, else `false`.
1608
1631
  * @example
1609
1632
  *
1610
1633
  * function Stooge(name, age) {
@@ -1621,7 +1644,7 @@
1621
1644
  * _.isPlainObject({ 'name': 'moe', 'age': 40 });
1622
1645
  * // => true
1623
1646
  */
1624
- var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) {
1647
+ var isPlainObject = function(value) {
1625
1648
  if (!(value && typeof value == 'object')) {
1626
1649
  return false;
1627
1650
  }
@@ -1640,7 +1663,7 @@
1640
1663
  * @memberOf _
1641
1664
  * @category Objects
1642
1665
  * @param {Mixed} value The value to check.
1643
- * @returns {Boolean} Returns `true` if the `value` is a regular expression, else `false`.
1666
+ * @returns {Boolean} Returns `true`, if the `value` is a regular expression, else `false`.
1644
1667
  * @example
1645
1668
  *
1646
1669
  * _.isRegExp(/moe/);
@@ -1657,7 +1680,7 @@
1657
1680
  * @memberOf _
1658
1681
  * @category Objects
1659
1682
  * @param {Mixed} value The value to check.
1660
- * @returns {Boolean} Returns `true` if the `value` is a string, else `false`.
1683
+ * @returns {Boolean} Returns `true`, if the `value` is a string, else `false`.
1661
1684
  * @example
1662
1685
  *
1663
1686
  * _.isString('moe');
@@ -1674,7 +1697,7 @@
1674
1697
  * @memberOf _
1675
1698
  * @category Objects
1676
1699
  * @param {Mixed} value The value to check.
1677
- * @returns {Boolean} Returns `true` if the `value` is `undefined`, else `false`.
1700
+ * @returns {Boolean} Returns `true`, if the `value` is `undefined`, else `false`.
1678
1701
  * @example
1679
1702
  *
1680
1703
  * _.isUndefined(void 0);
@@ -1685,100 +1708,137 @@
1685
1708
  }
1686
1709
 
1687
1710
  /**
1688
- * Creates an array composed of the own enumerable property names of `object`.
1689
- *
1690
- * @static
1691
- * @memberOf _
1692
- * @category Objects
1693
- * @param {Object} object The object to inspect.
1694
- * @returns {Array} Returns a new array of property names.
1695
- * @example
1696
- *
1697
- * _.keys({ 'one': 1, 'two': 2, 'three': 3 });
1698
- * // => ['one', 'two', 'three'] (order is not guaranteed)
1699
- */
1700
- var keys = !nativeKeys ? shimKeys : function(object) {
1701
- // avoid iterating over the `prototype` property
1702
- return typeof object == 'function' && propertyIsEnumerable.call(object, 'prototype')
1703
- ? shimKeys(object)
1704
- : (isObject(object) ? nativeKeys(object) : []);
1705
- };
1706
-
1707
- /**
1708
- * Merges enumerable properties of the source object(s) into the `destination`
1709
- * object. Subsequent sources will overwrite propery assignments of previous
1710
- * sources.
1711
+ * Recursively merges own enumerable properties of the source object(s), that
1712
+ * don't resolve to `undefined`, into the destination object. Subsequent sources
1713
+ * will overwrite propery assignments of previous sources. If a `callback` function
1714
+ * is passed, it will be executed to produce the merged values of the destination
1715
+ * and source properties. If `callback` returns `undefined`, merging will be
1716
+ * handled by the method instead. The `callback` is bound to `thisArg` and
1717
+ * invoked with two arguments; (objectValue, sourceValue).
1711
1718
  *
1712
1719
  * @static
1713
1720
  * @memberOf _
1714
1721
  * @category Objects
1715
1722
  * @param {Object} object The destination object.
1716
1723
  * @param {Object} [source1, source2, ...] The source objects.
1717
- * @param- {Object} [indicator] Internally used to indicate that the `stack`
1718
- * argument is an array of traversed objects instead of another source object.
1724
+ * @param {Function} [callback] The function to customize merging properties.
1725
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
1726
+ * @param- {Object} [deepIndicator] Internally used to indicate that `stackA`
1727
+ * and `stackB` are arrays of traversed objects instead of source objects.
1719
1728
  * @param- {Array} [stackA=[]] Internally used to track traversed source objects.
1720
1729
  * @param- {Array} [stackB=[]] Internally used to associate values with their
1721
1730
  * source counterparts.
1722
1731
  * @returns {Object} Returns the destination object.
1723
1732
  * @example
1724
1733
  *
1725
- * var stooges = [
1726
- * { 'name': 'moe' },
1727
- * { 'name': 'larry' }
1728
- * ];
1734
+ * var names = {
1735
+ * 'stooges': [
1736
+ * { 'name': 'moe' },
1737
+ * { 'name': 'larry' }
1738
+ * ]
1739
+ * };
1729
1740
  *
1730
- * var ages = [
1731
- * { 'age': 40 },
1732
- * { 'age': 50 }
1733
- * ];
1741
+ * var ages = {
1742
+ * 'stooges': [
1743
+ * { 'age': 40 },
1744
+ * { 'age': 50 }
1745
+ * ]
1746
+ * };
1747
+ *
1748
+ * _.merge(names, ages);
1749
+ * // => { 'stooges': [{ 'name': 'moe', 'age': 40 }, { 'name': 'larry', 'age': 50 }] }
1750
+ *
1751
+ * var food = {
1752
+ * 'fruits': ['apple'],
1753
+ * 'vegetables': ['beet']
1754
+ * };
1734
1755
  *
1735
- * _.merge(stooges, ages);
1736
- * // => [{ 'name': 'moe', 'age': 40 }, { 'name': 'larry', 'age': 50 }]
1756
+ * var otherFood = {
1757
+ * 'fruits': ['banana'],
1758
+ * 'vegetables': ['carrot']
1759
+ * };
1760
+ *
1761
+ * _.merge(food, otherFood, function(a, b) {
1762
+ * return _.isArray(a) ? a.concat(b) : undefined;
1763
+ * });
1764
+ * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] }
1737
1765
  */
1738
- function merge(object, source, indicator) {
1766
+ function merge(object, source, deepIndicator) {
1739
1767
  var args = arguments,
1740
1768
  index = 0,
1741
- length = 2,
1742
- stackA = args[3],
1743
- stackB = args[4];
1769
+ length = 2;
1744
1770
 
1745
- if (indicator !== indicatorObject) {
1771
+ if (!isObject(object)) {
1772
+ return object;
1773
+ }
1774
+ if (deepIndicator === indicatorObject) {
1775
+ var callback = args[3],
1776
+ stackA = args[4],
1777
+ stackB = args[5];
1778
+ } else {
1746
1779
  stackA = [];
1747
1780
  stackB = [];
1748
1781
 
1749
- // work with `_.reduce` by only using its callback `accumulator` and `value` arguments
1750
- if (typeof indicator != 'number') {
1782
+ // allows working with `_.reduce` and `_.reduceRight` without
1783
+ // using their `callback` arguments, `index|key` and `collection`
1784
+ if (typeof deepIndicator != 'number') {
1751
1785
  length = args.length;
1752
1786
  }
1787
+ if (length > 3 && typeof args[length - 2] == 'function') {
1788
+ callback = createCallback(args[--length - 1], args[length--], 2);
1789
+ } else if (length > 2 && typeof args[length - 1] == 'function') {
1790
+ callback = args[--length];
1791
+ }
1753
1792
  }
1754
1793
  while (++index < length) {
1755
- forOwn(args[index], function(source, key) {
1756
- var found, isArr, value;
1794
+ (isArray(args[index]) ? forEach : forOwn)(args[index], function(source, key) {
1795
+ var found,
1796
+ isArr,
1797
+ result = source,
1798
+ value = object[key];
1799
+
1757
1800
  if (source && ((isArr = isArray(source)) || isPlainObject(source))) {
1758
1801
  // avoid merging previously merged cyclic sources
1759
1802
  var stackLength = stackA.length;
1760
1803
  while (stackLength--) {
1761
- found = stackA[stackLength] == source;
1762
- if (found) {
1804
+ if ((found = stackA[stackLength] == source)) {
1805
+ value = stackB[stackLength];
1763
1806
  break;
1764
1807
  }
1765
1808
  }
1766
- if (found) {
1767
- object[key] = stackB[stackLength];
1768
- }
1769
- else {
1809
+ if (!found) {
1810
+ value = isArr
1811
+ ? (isArray(value) ? value : [])
1812
+ : (isPlainObject(value) ? value : {});
1813
+
1814
+ if (callback) {
1815
+ result = callback(value, source);
1816
+ if (typeof result != 'undefined') {
1817
+ value = result;
1818
+ }
1819
+ }
1770
1820
  // add `source` and associated `value` to the stack of traversed objects
1771
1821
  stackA.push(source);
1772
- stackB.push(value = (value = object[key], isArr)
1773
- ? (isArray(value) ? value : [])
1774
- : (isPlainObject(value) ? value : {})
1775
- );
1822
+ stackB.push(value);
1823
+
1776
1824
  // recursively merge objects and arrays (susceptible to call stack limits)
1777
- object[key] = merge(value, source, indicatorObject, stackA, stackB);
1825
+ if (!callback) {
1826
+ value = merge(value, source, indicatorObject, callback, stackA, stackB);
1827
+ }
1828
+ }
1829
+ }
1830
+ else {
1831
+ if (callback) {
1832
+ result = callback(value, source);
1833
+ if (typeof result == 'undefined') {
1834
+ result = source;
1835
+ }
1836
+ }
1837
+ if (typeof result != 'undefined') {
1838
+ value = result;
1778
1839
  }
1779
- } else if (source != null) {
1780
- object[key] = source;
1781
1840
  }
1841
+ object[key] = value;
1782
1842
  });
1783
1843
  }
1784
1844
  return object;
@@ -1787,9 +1847,10 @@
1787
1847
  /**
1788
1848
  * Creates a shallow clone of `object` excluding the specified properties.
1789
1849
  * Property names may be specified as individual arguments or as arrays of
1790
- * property names. If `callback` is passed, it will be executed for each property
1791
- * in the `object`, omitting the properties `callback` returns truthy for. The
1792
- * `callback` is bound to `thisArg` and invoked with three arguments; (value, key, object).
1850
+ * property names. If a `callback` function is passed, it will be executed
1851
+ * for each property in the `object`, omitting the properties `callback`
1852
+ * returns truthy for. The `callback` is bound to `thisArg` and invoked
1853
+ * with three arguments; (value, key, object).
1793
1854
  *
1794
1855
  * @static
1795
1856
  * @memberOf _
@@ -1801,11 +1862,11 @@
1801
1862
  * @returns {Object} Returns an object without the omitted properties.
1802
1863
  * @example
1803
1864
  *
1804
- * _.omit({ 'name': 'moe', 'age': 40, 'userid': 'moe1' }, 'userid');
1805
- * // => { 'name': 'moe', 'age': 40 }
1865
+ * _.omit({ 'name': 'moe', 'age': 40 }, 'age');
1866
+ * // => { 'name': 'moe' }
1806
1867
  *
1807
- * _.omit({ 'name': 'moe', '_hint': 'knucklehead', '_seed': '96c4eb' }, function(value, key) {
1808
- * return key.charAt(0) == '_';
1868
+ * _.omit({ 'name': 'moe', 'age': 40 }, function(value) {
1869
+ * return typeof value == 'number';
1809
1870
  * });
1810
1871
  * // => { 'name': 'moe' }
1811
1872
  */
@@ -1840,38 +1901,43 @@
1840
1901
  * @returns {Array} Returns new array of key-value pairs.
1841
1902
  * @example
1842
1903
  *
1843
- * _.pairs({ 'moe': 30, 'larry': 40, 'curly': 50 });
1844
- * // => [['moe', 30], ['larry', 40], ['curly', 50]] (order is not guaranteed)
1904
+ * _.pairs({ 'moe': 30, 'larry': 40 });
1905
+ * // => [['moe', 30], ['larry', 40]] (order is not guaranteed)
1845
1906
  */
1846
1907
  function pairs(object) {
1847
- var result = [];
1848
- forOwn(object, function(value, key) {
1849
- result.push([key, value]);
1850
- });
1908
+ var index = -1,
1909
+ props = keys(object),
1910
+ length = props.length,
1911
+ result = Array(length);
1912
+
1913
+ while (++index < length) {
1914
+ var key = props[index];
1915
+ result[index] = [key, object[key]];
1916
+ }
1851
1917
  return result;
1852
1918
  }
1853
1919
 
1854
1920
  /**
1855
1921
  * Creates a shallow clone of `object` composed of the specified properties.
1856
- * Property names may be specified as individual arguments or as arrays of
1857
- * property names. If `callback` is passed, it will be executed for each property
1858
- * in the `object`, picking the properties `callback` returns truthy for. The
1859
- * `callback` is bound to `thisArg` and invoked with three arguments; (value, key, object).
1922
+ * Property names may be specified as individual arguments or as arrays of property
1923
+ * names. If `callback` is passed, it will be executed for each property in the
1924
+ * `object`, picking the properties `callback` returns truthy for. The `callback`
1925
+ * is bound to `thisArg` and invoked with three arguments; (value, key, object).
1860
1926
  *
1861
1927
  * @static
1862
1928
  * @memberOf _
1863
1929
  * @category Objects
1864
1930
  * @param {Object} object The source object.
1865
- * @param {Function|String} callback|[prop1, prop2, ...] The properties to pick
1866
- * or the function called per iteration.
1931
+ * @param {Array|Function|String} callback|[prop1, prop2, ...] The function called
1932
+ * per iteration or properties to pick, either as individual arguments or arrays.
1867
1933
  * @param {Mixed} [thisArg] The `this` binding of `callback`.
1868
1934
  * @returns {Object} Returns an object composed of the picked properties.
1869
1935
  * @example
1870
1936
  *
1871
- * _.pick({ 'name': 'moe', 'age': 40, 'userid': 'moe1' }, 'name', 'age');
1872
- * // => { 'name': 'moe', 'age': 40 }
1937
+ * _.pick({ 'name': 'moe', '_userid': 'moe1' }, 'name');
1938
+ * // => { 'name': 'moe' }
1873
1939
  *
1874
- * _.pick({ 'name': 'moe', '_hint': 'knucklehead', '_seed': '96c4eb' }, function(value, key) {
1940
+ * _.pick({ 'name': 'moe', '_userid': 'moe1' }, function(value, key) {
1875
1941
  * return key.charAt(0) != '_';
1876
1942
  * });
1877
1943
  * // => { 'name': 'moe' }
@@ -1881,7 +1947,7 @@
1881
1947
  if (typeof callback != 'function') {
1882
1948
  var index = 0,
1883
1949
  props = concat.apply(arrayRef, arguments),
1884
- length = props.length;
1950
+ length = isObject(object) ? props.length : 0;
1885
1951
 
1886
1952
  while (++index < length) {
1887
1953
  var key = props[index];
@@ -1914,15 +1980,52 @@
1914
1980
  * // => [1, 2, 3]
1915
1981
  */
1916
1982
  function values(object) {
1917
- var result = [];
1918
- forOwn(object, function(value) {
1919
- result.push(value);
1920
- });
1983
+ var index = -1,
1984
+ props = keys(object),
1985
+ length = props.length,
1986
+ result = Array(length);
1987
+
1988
+ while (++index < length) {
1989
+ result[index] = object[props[index]];
1990
+ }
1991
+ return result;
1992
+ }
1993
+
1994
+ /*--------------------------------------------------------------------------*/
1995
+
1996
+ /**
1997
+ * Creates an array of elements from the specified indexes, or keys, of the
1998
+ * `collection`. Indexes may be specified as individual arguments or as arrays
1999
+ * of indexes.
2000
+ *
2001
+ * @static
2002
+ * @memberOf _
2003
+ * @category Collections
2004
+ * @param {Array|Object|String} collection The collection to iterate over.
2005
+ * @param {Array|Number|String} [index1, index2, ...] The indexes of
2006
+ * `collection` to retrieve, either as individual arguments or arrays.
2007
+ * @returns {Array} Returns a new array of elements corresponding to the
2008
+ * provided indexes.
2009
+ * @example
2010
+ *
2011
+ * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]);
2012
+ * // => ['a', 'c', 'e']
2013
+ *
2014
+ * _.at(['moe', 'larry', 'curly'], 0, 2);
2015
+ * // => ['moe', 'curly']
2016
+ */
2017
+ function at(collection) {
2018
+ var index = -1,
2019
+ props = concat.apply(arrayRef, slice(arguments, 1)),
2020
+ length = props.length,
2021
+ result = Array(length);
2022
+
2023
+ while(++index < length) {
2024
+ result[index] = collection[props[index]];
2025
+ }
1921
2026
  return result;
1922
2027
  }
1923
2028
 
1924
- /*--------------------------------------------------------------------------*/
1925
-
1926
2029
  /**
1927
2030
  * Checks if a given `target` element is present in a `collection` using strict
1928
2031
  * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
@@ -1972,18 +2075,25 @@
1972
2075
  }
1973
2076
 
1974
2077
  /**
1975
- * Creates an object composed of keys returned from running each element of
1976
- * `collection` through a `callback`. The corresponding value of each key is
1977
- * the number of times the key was returned by `callback`. The `callback` is
1978
- * bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
1979
- * The `callback` argument may also be the name of a property to count by (e.g. 'length').
2078
+ * Creates an object composed of keys returned from running each element of the
2079
+ * `collection` through the given `callback`. The corresponding value of each key
2080
+ * is the number of times the key was returned by the `callback`. The `callback`
2081
+ * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
2082
+ *
2083
+ * If a property name is passed for `callback`, the created "_.pluck" style
2084
+ * callback will return the property value of the given element.
2085
+ *
2086
+ * If an object is passed for `callback`, the created "_.where" style callback
2087
+ * will return `true` for elements that have the propeties of the given object,
2088
+ * else `false`.
1980
2089
  *
1981
2090
  * @static
1982
2091
  * @memberOf _
1983
2092
  * @category Collections
1984
2093
  * @param {Array|Object|String} collection The collection to iterate over.
1985
- * @param {Function|String} callback|property The function called per iteration
1986
- * or property name to count by.
2094
+ * @param {Function|Object|String} [callback=identity] The function called per
2095
+ * iteration. If a property name or object is passed, it will be used to create
2096
+ * a "_.pluck" or "_.where" style callback, respectively.
1987
2097
  * @param {Mixed} [thisArg] The `this` binding of `callback`.
1988
2098
  * @returns {Object} Returns the composed aggregate object.
1989
2099
  * @example
@@ -2002,7 +2112,7 @@
2002
2112
  callback = createCallback(callback, thisArg);
2003
2113
 
2004
2114
  forEach(collection, function(value, key, collection) {
2005
- key = callback(value, key, collection);
2115
+ key = callback(value, key, collection) + '';
2006
2116
  (hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1);
2007
2117
  });
2008
2118
  return result;
@@ -2013,12 +2123,21 @@
2013
2123
  * `collection`. The `callback` is bound to `thisArg` and invoked with three
2014
2124
  * arguments; (value, index|key, collection).
2015
2125
  *
2126
+ * If a property name is passed for `callback`, the created "_.pluck" style
2127
+ * callback will return the property value of the given element.
2128
+ *
2129
+ * If an object is passed for `callback`, the created "_.where" style callback
2130
+ * will return `true` for elements that have the propeties of the given object,
2131
+ * else `false`.
2132
+ *
2016
2133
  * @static
2017
2134
  * @memberOf _
2018
2135
  * @alias all
2019
2136
  * @category Collections
2020
2137
  * @param {Array|Object|String} collection The collection to iterate over.
2021
- * @param {Function} [callback=identity] The function called per iteration.
2138
+ * @param {Function|Object|String} [callback=identity] The function called per
2139
+ * iteration. If a property name or object is passed, it will be used to create
2140
+ * a "_.pluck" or "_.where" style callback, respectively.
2022
2141
  * @param {Mixed} [thisArg] The `this` binding of `callback`.
2023
2142
  * @returns {Boolean} Returns `true` if all elements pass the callback check,
2024
2143
  * else `false`.
@@ -2026,6 +2145,19 @@
2026
2145
  *
2027
2146
  * _.every([true, 1, null, 'yes'], Boolean);
2028
2147
  * // => false
2148
+ *
2149
+ * var stooges = [
2150
+ * { 'name': 'moe', 'age': 40 },
2151
+ * { 'name': 'larry', 'age': 50 }
2152
+ * ];
2153
+ *
2154
+ * // using "_.pluck" callback shorthand
2155
+ * _.every(stooges, 'age');
2156
+ * // => true
2157
+ *
2158
+ * // using "_.where" callback shorthand
2159
+ * _.every(stooges, { 'age': 50 });
2160
+ * // => false
2029
2161
  */
2030
2162
  function every(collection, callback, thisArg) {
2031
2163
  var result = true;
@@ -2053,18 +2185,40 @@
2053
2185
  * the `callback` returns truthy for. The `callback` is bound to `thisArg` and
2054
2186
  * invoked with three arguments; (value, index|key, collection).
2055
2187
  *
2188
+ * If a property name is passed for `callback`, the created "_.pluck" style
2189
+ * callback will return the property value of the given element.
2190
+ *
2191
+ * If an object is passed for `callback`, the created "_.where" style callback
2192
+ * will return `true` for elements that have the propeties of the given object,
2193
+ * else `false`.
2194
+ *
2056
2195
  * @static
2057
2196
  * @memberOf _
2058
2197
  * @alias select
2059
2198
  * @category Collections
2060
2199
  * @param {Array|Object|String} collection The collection to iterate over.
2061
- * @param {Function} [callback=identity] The function called per iteration.
2200
+ * @param {Function|Object|String} [callback=identity] The function called per
2201
+ * iteration. If a property name or object is passed, it will be used to create
2202
+ * a "_.pluck" or "_.where" style callback, respectively.
2062
2203
  * @param {Mixed} [thisArg] The `this` binding of `callback`.
2063
2204
  * @returns {Array} Returns a new array of elements that passed the callback check.
2064
2205
  * @example
2065
2206
  *
2066
2207
  * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
2067
2208
  * // => [2, 4, 6]
2209
+ *
2210
+ * var food = [
2211
+ * { 'name': 'apple', 'organic': false, 'type': 'fruit' },
2212
+ * { 'name': 'carrot', 'organic': true, 'type': 'vegetable' }
2213
+ * ];
2214
+ *
2215
+ * // using "_.pluck" callback shorthand
2216
+ * _.filter(food, 'organic');
2217
+ * // => [{ 'name': 'carrot', 'organic': true, 'type': 'vegetable' }]
2218
+ *
2219
+ * // using "_.where" callback shorthand
2220
+ * _.filter(food, { 'type': 'fruit' });
2221
+ * // => [{ 'name': 'apple', 'organic': false, 'type': 'fruit' }]
2068
2222
  */
2069
2223
  function filter(collection, callback, thisArg) {
2070
2224
  var result = [];
@@ -2091,17 +2245,25 @@
2091
2245
  }
2092
2246
 
2093
2247
  /**
2094
- * Examines each element in a `collection`, returning the first one the `callback`
2095
- * returns truthy for. The function returns as soon as it finds an acceptable
2096
- * element, and does not iterate over the entire `collection`. The `callback` is
2097
- * bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
2248
+ * Examines each element in a `collection`, returning the first that the `callback`
2249
+ * returns truthy for. The `callback` is bound to `thisArg` and invoked with three
2250
+ * arguments; (value, index|key, collection).
2251
+ *
2252
+ * If a property name is passed for `callback`, the created "_.pluck" style
2253
+ * callback will return the property value of the given element.
2254
+ *
2255
+ * If an object is passed for `callback`, the created "_.where" style callback
2256
+ * will return `true` for elements that have the propeties of the given object,
2257
+ * else `false`.
2098
2258
  *
2099
2259
  * @static
2100
2260
  * @memberOf _
2101
2261
  * @alias detect
2102
2262
  * @category Collections
2103
2263
  * @param {Array|Object|String} collection The collection to iterate over.
2104
- * @param {Function} [callback=identity] The function called per iteration.
2264
+ * @param {Function|Object|String} [callback=identity] The function called per
2265
+ * iteration. If a property name or object is passed, it will be used to create
2266
+ * a "_.pluck" or "_.where" style callback, respectively.
2105
2267
  * @param {Mixed} [thisArg] The `this` binding of `callback`.
2106
2268
  * @returns {Mixed} Returns the element that passed the callback check,
2107
2269
  * else `undefined`.
@@ -2109,6 +2271,21 @@
2109
2271
  *
2110
2272
  * var even = _.find([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
2111
2273
  * // => 2
2274
+ *
2275
+ * var food = [
2276
+ * { 'name': 'apple', 'organic': false, 'type': 'fruit' },
2277
+ * { 'name': 'banana', 'organic': true, 'type': 'fruit' },
2278
+ * { 'name': 'beet', 'organic': false, 'type': 'vegetable' },
2279
+ * { 'name': 'carrot', 'organic': true, 'type': 'vegetable' }
2280
+ * ];
2281
+ *
2282
+ * // using "_.where" callback shorthand
2283
+ * var veggie = _.find(food, { 'type': 'vegetable' });
2284
+ * // => { 'name': 'beet', 'organic': false, 'type': 'vegetable' }
2285
+ *
2286
+ * // using "_.pluck" callback shorthand
2287
+ * var healthy = _.find(food, 'organic');
2288
+ * // => { 'name': 'banana', 'organic': true, 'type': 'fruit' }
2112
2289
  */
2113
2290
  function find(collection, callback, thisArg) {
2114
2291
  var result;
@@ -2162,18 +2339,25 @@
2162
2339
  }
2163
2340
 
2164
2341
  /**
2165
- * Creates an object composed of keys returned from running each element of
2166
- * `collection` through a `callback`. The corresponding value of each key is an
2167
- * array of elements passed to `callback` that returned the key. The `callback`
2342
+ * Creates an object composed of keys returned from running each element of the
2343
+ * `collection` through the `callback`. The corresponding value of each key is
2344
+ * an array of elements passed to `callback` that returned the key. The `callback`
2168
2345
  * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
2169
- * The `callback` argument may also be the name of a property to group by (e.g. 'length').
2346
+ *
2347
+ * If a property name is passed for `callback`, the created "_.pluck" style
2348
+ * callback will return the property value of the given element.
2349
+ *
2350
+ * If an object is passed for `callback`, the created "_.where" style callback
2351
+ * will return `true` for elements that have the propeties of the given object,
2352
+ * else `false`
2170
2353
  *
2171
2354
  * @static
2172
2355
  * @memberOf _
2173
2356
  * @category Collections
2174
2357
  * @param {Array|Object|String} collection The collection to iterate over.
2175
- * @param {Function|String} callback|property The function called per iteration
2176
- * or property name to group by.
2358
+ * @param {Function|Object|String} [callback=identity] The function called per
2359
+ * iteration. If a property name or object is passed, it will be used to create
2360
+ * a "_.pluck" or "_.where" style callback, respectively.
2177
2361
  * @param {Mixed} [thisArg] The `this` binding of `callback`.
2178
2362
  * @returns {Object} Returns the composed aggregate object.
2179
2363
  * @example
@@ -2184,6 +2368,7 @@
2184
2368
  * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
2185
2369
  * // => { '4': [4.2], '6': [6.1, 6.4] }
2186
2370
  *
2371
+ * // using "_.pluck" callback shorthand
2187
2372
  * _.groupBy(['one', 'two', 'three'], 'length');
2188
2373
  * // => { '3': ['one', 'two'], '5': ['three'] }
2189
2374
  */
@@ -2192,7 +2377,7 @@
2192
2377
  callback = createCallback(callback, thisArg);
2193
2378
 
2194
2379
  forEach(collection, function(value, key, collection) {
2195
- key = callback(value, key, collection);
2380
+ key = callback(value, key, collection) + '';
2196
2381
  (hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value);
2197
2382
  });
2198
2383
  return result;
@@ -2201,7 +2386,7 @@
2201
2386
  /**
2202
2387
  * Invokes the method named by `methodName` on each element in the `collection`,
2203
2388
  * returning an array of the results of each invoked method. Additional arguments
2204
- * will be passed to each invoked method. If `methodName` is a function it will
2389
+ * will be passed to each invoked method. If `methodName` is a function, it will
2205
2390
  * be invoked for, and `this` bound to, each element in the `collection`.
2206
2391
  *
2207
2392
  * @static
@@ -2222,26 +2407,37 @@
2222
2407
  */
2223
2408
  function invoke(collection, methodName) {
2224
2409
  var args = slice(arguments, 2),
2410
+ index = -1,
2225
2411
  isFunc = typeof methodName == 'function',
2226
- result = [];
2412
+ length = collection ? collection.length : 0,
2413
+ result = Array(typeof length == 'number' ? length : 0);
2227
2414
 
2228
2415
  forEach(collection, function(value) {
2229
- result.push((isFunc ? methodName : value[methodName]).apply(value, args));
2416
+ result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args);
2230
2417
  });
2231
2418
  return result;
2232
2419
  }
2233
2420
 
2234
2421
  /**
2235
2422
  * Creates an array of values by running each element in the `collection`
2236
- * through a `callback`. The `callback` is bound to `thisArg` and invoked with
2423
+ * through the `callback`. The `callback` is bound to `thisArg` and invoked with
2237
2424
  * three arguments; (value, index|key, collection).
2238
2425
  *
2426
+ * If a property name is passed for `callback`, the created "_.pluck" style
2427
+ * callback will return the property value of the given element.
2428
+ *
2429
+ * If an object is passed for `callback`, the created "_.where" style callback
2430
+ * will return `true` for elements that have the propeties of the given object,
2431
+ * else `false`.
2432
+ *
2239
2433
  * @static
2240
2434
  * @memberOf _
2241
2435
  * @alias collect
2242
2436
  * @category Collections
2243
2437
  * @param {Array|Object|String} collection The collection to iterate over.
2244
- * @param {Function} [callback=identity] The function called per iteration.
2438
+ * @param {Function|Object|String} [callback=identity] The function called per
2439
+ * iteration. If a property name or object is passed, it will be used to create
2440
+ * a "_.pluck" or "_.where" style callback, respectively.
2245
2441
  * @param {Mixed} [thisArg] The `this` binding of `callback`.
2246
2442
  * @returns {Array} Returns a new array of the results of each `callback` execution.
2247
2443
  * @example
@@ -2251,6 +2447,15 @@
2251
2447
  *
2252
2448
  * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
2253
2449
  * // => [3, 6, 9] (order is not guaranteed)
2450
+ *
2451
+ * var stooges = [
2452
+ * { 'name': 'moe', 'age': 40 },
2453
+ * { 'name': 'larry', 'age': 50 }
2454
+ * ];
2455
+ *
2456
+ * // using "_.pluck" callback shorthand
2457
+ * _.map(stooges, 'name');
2458
+ * // => ['moe', 'larry']
2254
2459
  */
2255
2460
  function map(collection, callback, thisArg) {
2256
2461
  var index = -1,
@@ -2276,31 +2481,54 @@
2276
2481
  * criterion by which the value is ranked. The `callback` is bound to
2277
2482
  * `thisArg` and invoked with three arguments; (value, index, collection).
2278
2483
  *
2484
+ * If a property name is passed for `callback`, the created "_.pluck" style
2485
+ * callback will return the property value of the given element.
2486
+ *
2487
+ * If an object is passed for `callback`, the created "_.where" style callback
2488
+ * will return `true` for elements that have the propeties of the given object,
2489
+ * else `false`.
2490
+ *
2279
2491
  * @static
2280
2492
  * @memberOf _
2281
2493
  * @category Collections
2282
2494
  * @param {Array|Object|String} collection The collection to iterate over.
2283
- * @param {Function} [callback] The function called per iteration.
2495
+ * @param {Function|Object|String} [callback=identity] The function called per
2496
+ * iteration. If a property name or object is passed, it will be used to create
2497
+ * a "_.pluck" or "_.where" style callback, respectively.
2284
2498
  * @param {Mixed} [thisArg] The `this` binding of `callback`.
2285
2499
  * @returns {Mixed} Returns the maximum value.
2286
2500
  * @example
2287
2501
  *
2502
+ * _.max([4, 2, 8, 6]);
2503
+ * // => 8
2504
+ *
2288
2505
  * var stooges = [
2289
2506
  * { 'name': 'moe', 'age': 40 },
2290
- * { 'name': 'larry', 'age': 50 },
2291
- * { 'name': 'curly', 'age': 60 }
2507
+ * { 'name': 'larry', 'age': 50 }
2292
2508
  * ];
2293
2509
  *
2294
2510
  * _.max(stooges, function(stooge) { return stooge.age; });
2295
- * // => { 'name': 'curly', 'age': 60 };
2511
+ * // => { 'name': 'larry', 'age': 50 };
2512
+ *
2513
+ * // using "_.pluck" callback shorthand
2514
+ * _.max(stooges, 'age');
2515
+ * // => { 'name': 'larry', 'age': 50 };
2296
2516
  */
2297
2517
  function max(collection, callback, thisArg) {
2298
2518
  var computed = -Infinity,
2299
- index = -1,
2300
- length = collection ? collection.length : 0,
2301
2519
  result = computed;
2302
2520
 
2303
- if (callback || !isArray(collection)) {
2521
+ if (!callback && isArray(collection)) {
2522
+ var index = -1,
2523
+ length = collection.length;
2524
+
2525
+ while (++index < length) {
2526
+ var value = collection[index];
2527
+ if (value > result) {
2528
+ result = value;
2529
+ }
2530
+ }
2531
+ } else {
2304
2532
  callback = !callback && isString(collection)
2305
2533
  ? charAtCallback
2306
2534
  : createCallback(callback, thisArg);
@@ -2312,12 +2540,6 @@
2312
2540
  result = value;
2313
2541
  }
2314
2542
  });
2315
- } else {
2316
- while (++index < length) {
2317
- if (collection[index] > result) {
2318
- result = collection[index];
2319
- }
2320
- }
2321
2543
  }
2322
2544
  return result;
2323
2545
  }
@@ -2328,25 +2550,54 @@
2328
2550
  * criterion by which the value is ranked. The `callback` is bound to `thisArg`
2329
2551
  * and invoked with three arguments; (value, index, collection).
2330
2552
  *
2553
+ * If a property name is passed for `callback`, the created "_.pluck" style
2554
+ * callback will return the property value of the given element.
2555
+ *
2556
+ * If an object is passed for `callback`, the created "_.where" style callback
2557
+ * will return `true` for elements that have the propeties of the given object,
2558
+ * else `false`.
2559
+ *
2331
2560
  * @static
2332
2561
  * @memberOf _
2333
2562
  * @category Collections
2334
2563
  * @param {Array|Object|String} collection The collection to iterate over.
2335
- * @param {Function} [callback] The function called per iteration.
2564
+ * @param {Function|Object|String} [callback=identity] The function called per
2565
+ * iteration. If a property name or object is passed, it will be used to create
2566
+ * a "_.pluck" or "_.where" style callback, respectively.
2336
2567
  * @param {Mixed} [thisArg] The `this` binding of `callback`.
2337
2568
  * @returns {Mixed} Returns the minimum value.
2338
2569
  * @example
2339
2570
  *
2340
- * _.min([10, 5, 100, 2, 1000]);
2571
+ * _.min([4, 2, 8, 6]);
2341
2572
  * // => 2
2573
+ *
2574
+ * var stooges = [
2575
+ * { 'name': 'moe', 'age': 40 },
2576
+ * { 'name': 'larry', 'age': 50 }
2577
+ * ];
2578
+ *
2579
+ * _.min(stooges, function(stooge) { return stooge.age; });
2580
+ * // => { 'name': 'moe', 'age': 40 };
2581
+ *
2582
+ * // using "_.pluck" callback shorthand
2583
+ * _.min(stooges, 'age');
2584
+ * // => { 'name': 'moe', 'age': 40 };
2342
2585
  */
2343
2586
  function min(collection, callback, thisArg) {
2344
2587
  var computed = Infinity,
2345
- index = -1,
2346
- length = collection ? collection.length : 0,
2347
2588
  result = computed;
2348
2589
 
2349
- if (callback || !isArray(collection)) {
2590
+ if (!callback && isArray(collection)) {
2591
+ var index = -1,
2592
+ length = collection.length;
2593
+
2594
+ while (++index < length) {
2595
+ var value = collection[index];
2596
+ if (value < result) {
2597
+ result = value;
2598
+ }
2599
+ }
2600
+ } else {
2350
2601
  callback = !callback && isString(collection)
2351
2602
  ? charAtCallback
2352
2603
  : createCallback(callback, thisArg);
@@ -2358,22 +2609,16 @@
2358
2609
  result = value;
2359
2610
  }
2360
2611
  });
2361
- } else {
2362
- while (++index < length) {
2363
- if (collection[index] < result) {
2364
- result = collection[index];
2365
- }
2366
- }
2367
2612
  }
2368
2613
  return result;
2369
2614
  }
2370
2615
 
2371
2616
  /**
2372
- * Retrieves the value of a specified property from all elements in
2373
- * the `collection`.
2617
+ * Retrieves the value of a specified property from all elements in the `collection`.
2374
2618
  *
2375
2619
  * @static
2376
2620
  * @memberOf _
2621
+ * @type Function
2377
2622
  * @category Collections
2378
2623
  * @param {Array|Object|String} collection The collection to iterate over.
2379
2624
  * @param {String} property The property to pluck.
@@ -2382,22 +2627,21 @@
2382
2627
  *
2383
2628
  * var stooges = [
2384
2629
  * { 'name': 'moe', 'age': 40 },
2385
- * { 'name': 'larry', 'age': 50 },
2386
- * { 'name': 'curly', 'age': 60 }
2630
+ * { 'name': 'larry', 'age': 50 }
2387
2631
  * ];
2388
2632
  *
2389
2633
  * _.pluck(stooges, 'name');
2390
- * // => ['moe', 'larry', 'curly']
2634
+ * // => ['moe', 'larry']
2391
2635
  */
2392
- function pluck(collection, property) {
2393
- return map(collection, property + '');
2394
- }
2636
+ var pluck = map;
2395
2637
 
2396
2638
  /**
2397
- * Boils down a `collection` to a single value. The initial state of the
2398
- * reduction is `accumulator` and each successive step of it should be returned
2399
- * by the `callback`. The `callback` is bound to `thisArg` and invoked with 4
2400
- * arguments; for arrays they are (accumulator, value, index|key, collection).
2639
+ * Reduces a `collection` to a value that is the accumulated result of running
2640
+ * each element in the `collection` through the `callback`, where each successive
2641
+ * `callback` execution consumes the return value of the previous execution.
2642
+ * If `accumulator` is not passed, the first element of the `collection` will be
2643
+ * used as the initial `accumulator` value. The `callback` is bound to `thisArg`
2644
+ * and invoked with four arguments; (accumulator, value, index|key, collection).
2401
2645
  *
2402
2646
  * @static
2403
2647
  * @memberOf _
@@ -2410,12 +2654,20 @@
2410
2654
  * @returns {Mixed} Returns the accumulated value.
2411
2655
  * @example
2412
2656
  *
2413
- * var sum = _.reduce([1, 2, 3], function(memo, num) { return memo + num; });
2657
+ * var sum = _.reduce([1, 2, 3], function(sum, num) {
2658
+ * return sum + num;
2659
+ * });
2414
2660
  * // => 6
2661
+ *
2662
+ * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
2663
+ * result[key] = num * 3;
2664
+ * return result;
2665
+ * }, {});
2666
+ * // => { 'a': 3, 'b': 6, 'c': 9 }
2415
2667
  */
2416
2668
  function reduce(collection, callback, accumulator, thisArg) {
2417
2669
  var noaccum = arguments.length < 3;
2418
- callback = createCallback(callback, thisArg, indicatorObject);
2670
+ callback = createCallback(callback, thisArg, 4);
2419
2671
 
2420
2672
  if (isArray(collection)) {
2421
2673
  var index = -1,
@@ -2438,7 +2690,8 @@
2438
2690
  }
2439
2691
 
2440
2692
  /**
2441
- * The right-associative version of `_.reduce`.
2693
+ * This method is similar to `_.reduce`, except that it iterates over a
2694
+ * `collection` from right to left.
2442
2695
  *
2443
2696
  * @static
2444
2697
  * @memberOf _
@@ -2456,35 +2709,42 @@
2456
2709
  * // => [4, 5, 2, 3, 0, 1]
2457
2710
  */
2458
2711
  function reduceRight(collection, callback, accumulator, thisArg) {
2459
- var iteratee = collection,
2712
+ var iterable = collection,
2460
2713
  length = collection ? collection.length : 0,
2461
2714
  noaccum = arguments.length < 3;
2462
2715
 
2463
2716
  if (typeof length != 'number') {
2464
2717
  var props = keys(collection);
2465
2718
  length = props.length;
2466
- } else if (noCharByIndex && isString(collection)) {
2467
- iteratee = collection.split('');
2468
2719
  }
2469
- callback = createCallback(callback, thisArg, indicatorObject);
2720
+ callback = createCallback(callback, thisArg, 4);
2470
2721
  forEach(collection, function(value, index, collection) {
2471
2722
  index = props ? props[--length] : --length;
2472
2723
  accumulator = noaccum
2473
- ? (noaccum = false, iteratee[index])
2474
- : callback(accumulator, iteratee[index], index, collection);
2724
+ ? (noaccum = false, iterable[index])
2725
+ : callback(accumulator, iterable[index], index, collection);
2475
2726
  });
2476
2727
  return accumulator;
2477
2728
  }
2478
2729
 
2479
2730
  /**
2480
- * The opposite of `_.filter`, this method returns the values of a
2731
+ * The opposite of `_.filter`, this method returns the elements of a
2481
2732
  * `collection` that `callback` does **not** return truthy for.
2482
2733
  *
2734
+ * If a property name is passed for `callback`, the created "_.pluck" style
2735
+ * callback will return the property value of the given element.
2736
+ *
2737
+ * If an object is passed for `callback`, the created "_.where" style callback
2738
+ * will return `true` for elements that have the propeties of the given object,
2739
+ * else `false`.
2740
+ *
2483
2741
  * @static
2484
2742
  * @memberOf _
2485
2743
  * @category Collections
2486
2744
  * @param {Array|Object|String} collection The collection to iterate over.
2487
- * @param {Function} [callback=identity] The function called per iteration.
2745
+ * @param {Function|Object|String} [callback=identity] The function called per
2746
+ * iteration. If a property name or object is passed, it will be used to create
2747
+ * a "_.pluck" or "_.where" style callback, respectively.
2488
2748
  * @param {Mixed} [thisArg] The `this` binding of `callback`.
2489
2749
  * @returns {Array} Returns a new array of elements that did **not** pass the
2490
2750
  * callback check.
@@ -2492,6 +2752,19 @@
2492
2752
  *
2493
2753
  * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
2494
2754
  * // => [1, 3, 5]
2755
+ *
2756
+ * var food = [
2757
+ * { 'name': 'apple', 'organic': false, 'type': 'fruit' },
2758
+ * { 'name': 'carrot', 'organic': true, 'type': 'vegetable' }
2759
+ * ];
2760
+ *
2761
+ * // using "_.pluck" callback shorthand
2762
+ * _.reject(food, 'organic');
2763
+ * // => [{ 'name': 'apple', 'organic': false, 'type': 'fruit' }]
2764
+ *
2765
+ * // using "_.where" callback shorthand
2766
+ * _.reject(food, { 'type': 'fruit' });
2767
+ * // => [{ 'name': 'carrot', 'organic': true, 'type': 'vegetable' }]
2495
2768
  */
2496
2769
  function reject(collection, callback, thisArg) {
2497
2770
  callback = createCallback(callback, thisArg);
@@ -2516,7 +2789,8 @@
2516
2789
  */
2517
2790
  function shuffle(collection) {
2518
2791
  var index = -1,
2519
- result = Array(collection ? collection.length : 0);
2792
+ length = collection ? collection.length : 0,
2793
+ result = Array(typeof length == 'number' ? length : 0);
2520
2794
 
2521
2795
  forEach(collection, function(value) {
2522
2796
  var rand = floor(nativeRandom() * (++index + 1));
@@ -2557,12 +2831,21 @@
2557
2831
  * does not iterate over the entire `collection`. The `callback` is bound to
2558
2832
  * `thisArg` and invoked with three arguments; (value, index|key, collection).
2559
2833
  *
2834
+ * If a property name is passed for `callback`, the created "_.pluck" style
2835
+ * callback will return the property value of the given element.
2836
+ *
2837
+ * If an object is passed for `callback`, the created "_.where" style callback
2838
+ * will return `true` for elements that have the propeties of the given object,
2839
+ * else `false`.
2840
+ *
2560
2841
  * @static
2561
2842
  * @memberOf _
2562
2843
  * @alias any
2563
2844
  * @category Collections
2564
2845
  * @param {Array|Object|String} collection The collection to iterate over.
2565
- * @param {Function} [callback=identity] The function called per iteration.
2846
+ * @param {Function|Object|String} [callback=identity] The function called per
2847
+ * iteration. If a property name or object is passed, it will be used to create
2848
+ * a "_.pluck" or "_.where" style callback, respectively.
2566
2849
  * @param {Mixed} [thisArg] The `this` binding of `callback`.
2567
2850
  * @returns {Boolean} Returns `true` if any element passes the callback check,
2568
2851
  * else `false`.
@@ -2570,6 +2853,19 @@
2570
2853
  *
2571
2854
  * _.some([null, 0, 'yes', false], Boolean);
2572
2855
  * // => true
2856
+ *
2857
+ * var food = [
2858
+ * { 'name': 'apple', 'organic': false, 'type': 'fruit' },
2859
+ * { 'name': 'carrot', 'organic': true, 'type': 'vegetable' }
2860
+ * ];
2861
+ *
2862
+ * // using "_.pluck" callback shorthand
2863
+ * _.some(food, 'organic');
2864
+ * // => true
2865
+ *
2866
+ * // using "_.where" callback shorthand
2867
+ * _.some(food, { 'type': 'meat' });
2868
+ * // => false
2573
2869
  */
2574
2870
  function some(collection, callback, thisArg) {
2575
2871
  var result;
@@ -2593,17 +2889,26 @@
2593
2889
  }
2594
2890
 
2595
2891
  /**
2596
- * Creates an array, stable sorted in ascending order by the results of
2597
- * running each element of `collection` through a `callback`. The `callback`
2598
- * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
2599
- * The `callback` argument may also be the name of a property to sort by (e.g. 'length').
2892
+ * Creates an array of elements, sorted in ascending order by the results of
2893
+ * running each element in the `collection` through the `callback`. This method
2894
+ * performs a stable sort, that is, it will preserve the original sort order of
2895
+ * equal elements. The `callback` is bound to `thisArg` and invoked with three
2896
+ * arguments; (value, index|key, collection).
2897
+ *
2898
+ * If a property name is passed for `callback`, the created "_.pluck" style
2899
+ * callback will return the property value of the given element.
2900
+ *
2901
+ * If an object is passed for `callback`, the created "_.where" style callback
2902
+ * will return `true` for elements that have the propeties of the given object,
2903
+ * else `false`.
2600
2904
  *
2601
2905
  * @static
2602
2906
  * @memberOf _
2603
2907
  * @category Collections
2604
2908
  * @param {Array|Object|String} collection The collection to iterate over.
2605
- * @param {Function|String} callback|property The function called per iteration
2606
- * or property name to sort by.
2909
+ * @param {Function|Object|String} [callback=identity] The function called per
2910
+ * iteration. If a property name or object is passed, it will be used to create
2911
+ * a "_.pluck" or "_.where" style callback, respectively.
2607
2912
  * @param {Mixed} [thisArg] The `this` binding of `callback`.
2608
2913
  * @returns {Array} Returns a new array of sorted elements.
2609
2914
  * @example
@@ -2614,22 +2919,25 @@
2614
2919
  * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math);
2615
2920
  * // => [3, 1, 2]
2616
2921
  *
2617
- * _.sortBy(['larry', 'brendan', 'moe'], 'length');
2618
- * // => ['moe', 'larry', 'brendan']
2922
+ * // using "_.pluck" callback shorthand
2923
+ * _.sortBy(['banana', 'strawberry', 'apple'], 'length');
2924
+ * // => ['apple', 'banana', 'strawberry']
2619
2925
  */
2620
2926
  function sortBy(collection, callback, thisArg) {
2621
- var result = [];
2622
- callback = createCallback(callback, thisArg);
2927
+ var index = -1,
2928
+ length = collection ? collection.length : 0,
2929
+ result = Array(typeof length == 'number' ? length : 0);
2623
2930
 
2624
- forEach(collection, function(value, index, collection) {
2625
- result.push({
2626
- 'criteria': callback(value, index, collection),
2931
+ callback = createCallback(callback, thisArg);
2932
+ forEach(collection, function(value, key, collection) {
2933
+ result[++index] = {
2934
+ 'criteria': callback(value, key, collection),
2627
2935
  'index': index,
2628
2936
  'value': value
2629
- });
2937
+ };
2630
2938
  });
2631
2939
 
2632
- var length = result.length;
2940
+ length = result.length;
2633
2941
  result.sort(compareAscending);
2634
2942
  while (length--) {
2635
2943
  result[length] = result[length].value;
@@ -2651,49 +2959,36 @@
2651
2959
  * // => [2, 3, 4]
2652
2960
  */
2653
2961
  function toArray(collection) {
2654
- var length = collection ? collection.length : 0;
2655
- if (typeof length == 'number') {
2656
- return noCharByIndex && isString(collection)
2657
- ? collection.split('')
2658
- : slice(collection);
2962
+ if (collection && typeof collection.length == 'number') {
2963
+ return slice(collection);
2659
2964
  }
2660
2965
  return values(collection);
2661
2966
  }
2662
2967
 
2663
2968
  /**
2664
2969
  * Examines each element in a `collection`, returning an array of all elements
2665
- * that contain the given `properties`.
2970
+ * that have the given `properties`. When checking `properties`, this method
2971
+ * performs a deep comparison between values to determine if they are equivalent
2972
+ * to each other.
2666
2973
  *
2667
2974
  * @static
2668
2975
  * @memberOf _
2976
+ * @type Function
2669
2977
  * @category Collections
2670
2978
  * @param {Array|Object|String} collection The collection to iterate over.
2671
2979
  * @param {Object} properties The object of property values to filter by.
2672
- * @returns {Array} Returns a new array of elements that contain the given `properties`.
2980
+ * @returns {Array} Returns a new array of elements that have the given `properties`.
2673
2981
  * @example
2674
2982
  *
2675
2983
  * var stooges = [
2676
2984
  * { 'name': 'moe', 'age': 40 },
2677
- * { 'name': 'larry', 'age': 50 },
2678
- * { 'name': 'curly', 'age': 60 }
2985
+ * { 'name': 'larry', 'age': 50 }
2679
2986
  * ];
2680
2987
  *
2681
2988
  * _.where(stooges, { 'age': 40 });
2682
2989
  * // => [{ 'name': 'moe', 'age': 40 }]
2683
2990
  */
2684
- function where(collection, properties) {
2685
- var props = keys(properties);
2686
- return filter(collection, function(object) {
2687
- var length = props.length;
2688
- while (length--) {
2689
- var result = object[props[length]] === properties[props[length]];
2690
- if (!result) {
2691
- break;
2692
- }
2693
- }
2694
- return !!result;
2695
- });
2696
- }
2991
+ var where = filter;
2697
2992
 
2698
2993
  /*--------------------------------------------------------------------------*/
2699
2994
 
@@ -2758,30 +3053,79 @@
2758
3053
  }
2759
3054
 
2760
3055
  /**
2761
- * Gets the first element of the `array`. Pass `n` to return the first `n`
2762
- * elements of the `array`.
3056
+ * Gets the first element of the `array`. If a number `n` is passed, the first
3057
+ * `n` elements of the `array` are returned. If a `callback` function is passed,
3058
+ * the first elements the `callback` returns truthy for are returned. The `callback`
3059
+ * is bound to `thisArg` and invoked with three arguments; (value, index, array).
3060
+ *
3061
+ * If a property name is passed for `callback`, the created "_.pluck" style
3062
+ * callback will return the property value of the given element.
3063
+ *
3064
+ * If an object is passed for `callback`, the created "_.where" style callback
3065
+ * will return `true` for elements that have the propeties of the given object,
3066
+ * else `false`.
2763
3067
  *
2764
3068
  * @static
2765
3069
  * @memberOf _
2766
3070
  * @alias head, take
2767
3071
  * @category Arrays
2768
3072
  * @param {Array} array The array to query.
2769
- * @param {Number} [n] The number of elements to return.
2770
- * @param- {Object} [guard] Internally used to allow this method to work with
2771
- * others like `_.map` without using their callback `index` argument for `n`.
2772
- * @returns {Mixed} Returns the first element, or an array of the first `n`
2773
- * elements, of `array`.
3073
+ * @param {Function|Object|Number|String} [callback|n] The function called
3074
+ * per element or the number of elements to return. If a property name or
3075
+ * object is passed, it will be used to create a "_.pluck" or "_.where"
3076
+ * style callback, respectively.
3077
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
3078
+ * @returns {Mixed} Returns the first element(s) of `array`.
2774
3079
  * @example
2775
3080
  *
2776
- * _.first([5, 4, 3, 2, 1]);
2777
- * // => 5
3081
+ * _.first([1, 2, 3]);
3082
+ * // => 1
3083
+ *
3084
+ * _.first([1, 2, 3], 2);
3085
+ * // => [1, 2]
3086
+ *
3087
+ * _.first([1, 2, 3], function(num) {
3088
+ * return num < 3;
3089
+ * });
3090
+ * // => [1, 2]
3091
+ *
3092
+ * var food = [
3093
+ * { 'name': 'banana', 'organic': true },
3094
+ * { 'name': 'beet', 'organic': false },
3095
+ * ];
3096
+ *
3097
+ * // using "_.pluck" callback shorthand
3098
+ * _.first(food, 'organic');
3099
+ * // => [{ 'name': 'banana', 'organic': true }]
3100
+ *
3101
+ * var food = [
3102
+ * { 'name': 'apple', 'type': 'fruit' },
3103
+ * { 'name': 'banana', 'type': 'fruit' },
3104
+ * { 'name': 'beet', 'type': 'vegetable' }
3105
+ * ];
3106
+ *
3107
+ * // using "_.where" callback shorthand
3108
+ * _.first(food, { 'type': 'fruit' });
3109
+ * // => [{ 'name': 'apple', 'type': 'fruit' }, { 'name': 'banana', 'type': 'fruit' }]
2778
3110
  */
2779
- function first(array, n, guard) {
3111
+ function first(array, callback, thisArg) {
2780
3112
  if (array) {
2781
- var length = array.length;
2782
- return (n == null || guard)
2783
- ? array[0]
2784
- : slice(array, 0, nativeMin(nativeMax(0, n), length));
3113
+ var n = 0,
3114
+ length = array.length;
3115
+
3116
+ if (typeof callback != 'number' && callback != null) {
3117
+ var index = -1;
3118
+ callback = createCallback(callback, thisArg);
3119
+ while (++index < length && callback(array[index], index, array)) {
3120
+ n++;
3121
+ }
3122
+ } else {
3123
+ n = callback;
3124
+ if (n == null || thisArg) {
3125
+ return array[0];
3126
+ }
3127
+ }
3128
+ return slice(array, 0, nativeMin(nativeMax(0, n), length));
2785
3129
  }
2786
3130
  }
2787
3131
 
@@ -2864,28 +3208,77 @@
2864
3208
  }
2865
3209
 
2866
3210
  /**
2867
- * Gets all but the last element of `array`. Pass `n` to exclude the last `n`
2868
- * elements from the result.
3211
+ * Gets all but the last element of `array`. If a number `n` is passed, the
3212
+ * last `n` elements are excluded from the result. If a `callback` function
3213
+ * is passed, the last elements the `callback` returns truthy for are excluded
3214
+ * from the result. The `callback` is bound to `thisArg` and invoked with three
3215
+ * arguments; (value, index, array).
3216
+ *
3217
+ * If a property name is passed for `callback`, the created "_.pluck" style
3218
+ * callback will return the property value of the given element.
3219
+ *
3220
+ * If an object is passed for `callback`, the created "_.where" style callback
3221
+ * will return `true` for elements that have the propeties of the given object,
3222
+ * else `false`.
2869
3223
  *
2870
3224
  * @static
2871
3225
  * @memberOf _
2872
3226
  * @category Arrays
2873
3227
  * @param {Array} array The array to query.
2874
- * @param {Number} [n=1] The number of elements to exclude.
2875
- * @param- {Object} [guard] Internally used to allow this method to work with
2876
- * others like `_.map` without using their callback `index` argument for `n`.
2877
- * @returns {Array} Returns all but the last element, or `n` elements, of `array`.
3228
+ * @param {Function|Object|Number|String} [callback|n=1] The function called
3229
+ * per element or the number of elements to exclude. If a property name or
3230
+ * object is passed, it will be used to create a "_.pluck" or "_.where"
3231
+ * style callback, respectively.
3232
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
3233
+ * @returns {Array} Returns a slice of `array`.
2878
3234
  * @example
2879
3235
  *
2880
- * _.initial([3, 2, 1]);
2881
- * // => [3, 2]
3236
+ * _.initial([1, 2, 3]);
3237
+ * // => [1, 2]
3238
+ *
3239
+ * _.initial([1, 2, 3], 2);
3240
+ * // => [1]
3241
+ *
3242
+ * _.initial([1, 2, 3], function(num) {
3243
+ * return num > 1;
3244
+ * });
3245
+ * // => [1]
3246
+ *
3247
+ * var food = [
3248
+ * { 'name': 'beet', 'organic': false },
3249
+ * { 'name': 'carrot', 'organic': true }
3250
+ * ];
3251
+ *
3252
+ * // using "_.pluck" callback shorthand
3253
+ * _.initial(food, 'organic');
3254
+ * // => [{ 'name': 'beet', 'organic': false }]
3255
+ *
3256
+ * var food = [
3257
+ * { 'name': 'banana', 'type': 'fruit' },
3258
+ * { 'name': 'beet', 'type': 'vegetable' },
3259
+ * { 'name': 'carrot', 'type': 'vegetable' }
3260
+ * ];
3261
+ *
3262
+ * // using "_.where" callback shorthand
3263
+ * _.initial(food, { 'type': 'vegetable' });
3264
+ * // => [{ 'name': 'banana', 'type': 'fruit' }]
2882
3265
  */
2883
- function initial(array, n, guard) {
3266
+ function initial(array, callback, thisArg) {
2884
3267
  if (!array) {
2885
3268
  return [];
2886
3269
  }
2887
- var length = array.length;
2888
- n = n == null || guard ? 1 : n || 0;
3270
+ var n = 0,
3271
+ length = array.length;
3272
+
3273
+ if (typeof callback != 'number' && callback != null) {
3274
+ var index = length;
3275
+ callback = createCallback(callback, thisArg);
3276
+ while (index-- && callback(array[index], index, array)) {
3277
+ n++;
3278
+ }
3279
+ } else {
3280
+ n = (callback == null || thisArg) ? 1 : callback || n;
3281
+ }
2889
3282
  return slice(array, 0, nativeMin(nativeMax(0, length - n), length));
2890
3283
  }
2891
3284
 
@@ -2940,27 +3333,79 @@
2940
3333
  }
2941
3334
 
2942
3335
  /**
2943
- * Gets the last element of the `array`. Pass `n` to return the last `n`
2944
- * elements of the `array`.
3336
+ * Gets the last element of the `array`. If a number `n` is passed, the last
3337
+ * `n` elements of the `array` are returned. If a `callback` function is passed,
3338
+ * the last elements the `callback` returns truthy for are returned. The `callback`
3339
+ * is bound to `thisArg` and invoked with three arguments; (value, index, array).
3340
+ *
3341
+ *
3342
+ * If a property name is passed for `callback`, the created "_.pluck" style
3343
+ * callback will return the property value of the given element.
3344
+ *
3345
+ * If an object is passed for `callback`, the created "_.where" style callback
3346
+ * will return `true` for elements that have the propeties of the given object,
3347
+ * else `false`.
2945
3348
  *
2946
3349
  * @static
2947
3350
  * @memberOf _
2948
3351
  * @category Arrays
2949
3352
  * @param {Array} array The array to query.
2950
- * @param {Number} [n] The number of elements to return.
2951
- * @param- {Object} [guard] Internally used to allow this method to work with
2952
- * others like `_.map` without using their callback `index` argument for `n`.
2953
- * @returns {Mixed} Returns the last element, or an array of the last `n`
2954
- * elements, of `array`.
3353
+ * @param {Function|Object|Number|String} [callback|n] The function called
3354
+ * per element or the number of elements to return. If a property name or
3355
+ * object is passed, it will be used to create a "_.pluck" or "_.where"
3356
+ * style callback, respectively.
3357
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
3358
+ * @returns {Mixed} Returns the last element(s) of `array`.
2955
3359
  * @example
2956
3360
  *
2957
- * _.last([3, 2, 1]);
2958
- * // => 1
3361
+ * _.last([1, 2, 3]);
3362
+ * // => 3
3363
+ *
3364
+ * _.last([1, 2, 3], 2);
3365
+ * // => [2, 3]
3366
+ *
3367
+ * _.last([1, 2, 3], function(num) {
3368
+ * return num > 1;
3369
+ * });
3370
+ * // => [2, 3]
3371
+ *
3372
+ * var food = [
3373
+ * { 'name': 'beet', 'organic': false },
3374
+ * { 'name': 'carrot', 'organic': true }
3375
+ * ];
3376
+ *
3377
+ * // using "_.pluck" callback shorthand
3378
+ * _.last(food, 'organic');
3379
+ * // => [{ 'name': 'carrot', 'organic': true }]
3380
+ *
3381
+ * var food = [
3382
+ * { 'name': 'banana', 'type': 'fruit' },
3383
+ * { 'name': 'beet', 'type': 'vegetable' },
3384
+ * { 'name': 'carrot', 'type': 'vegetable' }
3385
+ * ];
3386
+ *
3387
+ * // using "_.where" callback shorthand
3388
+ * _.last(food, { 'type': 'vegetable' });
3389
+ * // => [{ 'name': 'beet', 'type': 'vegetable' }, { 'name': 'carrot', 'type': 'vegetable' }]
2959
3390
  */
2960
- function last(array, n, guard) {
3391
+ function last(array, callback, thisArg) {
2961
3392
  if (array) {
2962
- var length = array.length;
2963
- return (n == null || guard) ? array[length - 1] : slice(array, nativeMax(0, length - n));
3393
+ var n = 0,
3394
+ length = array.length;
3395
+
3396
+ if (typeof callback != 'number' && callback != null) {
3397
+ var index = length;
3398
+ callback = createCallback(callback, thisArg);
3399
+ while (index-- && callback(array[index], index, array)) {
3400
+ n++;
3401
+ }
3402
+ } else {
3403
+ n = callback;
3404
+ if (n == null || thisArg) {
3405
+ return array[length - 1];
3406
+ }
3407
+ }
3408
+ return slice(array, nativeMax(0, length - n));
2964
3409
  }
2965
3410
  }
2966
3411
 
@@ -3011,8 +3456,8 @@
3011
3456
  * corresponding values.
3012
3457
  * @example
3013
3458
  *
3014
- * _.object(['moe', 'larry', 'curly'], [30, 40, 50]);
3015
- * // => { 'moe': 30, 'larry': 40, 'curly': 50 }
3459
+ * _.object(['moe', 'larry'], [30, 40]);
3460
+ * // => { 'moe': 30, 'larry': 40 }
3016
3461
  */
3017
3462
  function object(keys, values) {
3018
3463
  var index = -1,
@@ -3032,8 +3477,7 @@
3032
3477
 
3033
3478
  /**
3034
3479
  * Creates an array of numbers (positive and/or negative) progressing from
3035
- * `start` up to but not including `stop`. This method is a port of Python's
3036
- * `range()` function. See http://docs.python.org/library/functions.html#range.
3480
+ * `start` up to but not including `end`.
3037
3481
  *
3038
3482
  * @static
3039
3483
  * @memberOf _
@@ -3081,25 +3525,76 @@
3081
3525
  }
3082
3526
 
3083
3527
  /**
3084
- * The opposite of `_.initial`, this method gets all but the first value of
3085
- * `array`. Pass `n` to exclude the first `n` values from the result.
3528
+ * The opposite of `_.initial`, this method gets all but the first value of `array`.
3529
+ * If a number `n` is passed, the first `n` values are excluded from the result.
3530
+ * If a `callback` function is passed, the first elements the `callback` returns
3531
+ * truthy for are excluded from the result. The `callback` is bound to `thisArg`
3532
+ * and invoked with three arguments; (value, index, array).
3533
+ *
3534
+ * If a property name is passed for `callback`, the created "_.pluck" style
3535
+ * callback will return the property value of the given element.
3536
+ *
3537
+ * If an object is passed for `callback`, the created "_.where" style callback
3538
+ * will return `true` for elements that have the propeties of the given object,
3539
+ * else `false`.
3086
3540
  *
3087
3541
  * @static
3088
3542
  * @memberOf _
3089
3543
  * @alias drop, tail
3090
3544
  * @category Arrays
3091
3545
  * @param {Array} array The array to query.
3092
- * @param {Number} [n=1] The number of elements to exclude.
3093
- * @param- {Object} [guard] Internally used to allow this method to work with
3094
- * others like `_.map` without using their callback `index` argument for `n`.
3095
- * @returns {Array} Returns all but the first element, or `n` elements, of `array`.
3546
+ * @param {Function|Object|Number|String} [callback|n=1] The function called
3547
+ * per element or the number of elements to exclude. If a property name or
3548
+ * object is passed, it will be used to create a "_.pluck" or "_.where"
3549
+ * style callback, respectively.
3550
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
3551
+ * @returns {Array} Returns a slice of `array`.
3096
3552
  * @example
3097
3553
  *
3098
- * _.rest([3, 2, 1]);
3099
- * // => [2, 1]
3554
+ * _.rest([1, 2, 3]);
3555
+ * // => [2, 3]
3556
+ *
3557
+ * _.rest([1, 2, 3], 2);
3558
+ * // => [3]
3559
+ *
3560
+ * _.rest([1, 2, 3], function(num) {
3561
+ * return num < 3;
3562
+ * });
3563
+ * // => [3]
3564
+ *
3565
+ * var food = [
3566
+ * { 'name': 'banana', 'organic': true },
3567
+ * { 'name': 'beet', 'organic': false },
3568
+ * ];
3569
+ *
3570
+ * // using "_.pluck" callback shorthand
3571
+ * _.rest(food, 'organic');
3572
+ * // => [{ 'name': 'beet', 'organic': false }]
3573
+ *
3574
+ * var food = [
3575
+ * { 'name': 'apple', 'type': 'fruit' },
3576
+ * { 'name': 'banana', 'type': 'fruit' },
3577
+ * { 'name': 'beet', 'type': 'vegetable' }
3578
+ * ];
3579
+ *
3580
+ * // using "_.where" callback shorthand
3581
+ * _.rest(food, { 'type': 'fruit' });
3582
+ * // => [{ 'name': 'beet', 'type': 'vegetable' }]
3100
3583
  */
3101
- function rest(array, n, guard) {
3102
- return slice(array, (n == null || guard) ? 1 : nativeMax(0, n));
3584
+ function rest(array, callback, thisArg) {
3585
+ if (typeof callback != 'number' && callback != null) {
3586
+ var n = 0,
3587
+ index = -1,
3588
+ length = array ? array.length : 0;
3589
+
3590
+ callback = createCallback(callback, thisArg);
3591
+ while (++index < length && callback(array[index], index, array)) {
3592
+ n++;
3593
+ }
3594
+ } else {
3595
+ n = (callback == null || thisArg) ? 1 : nativeMax(0, callback);
3596
+ }
3597
+ return slice(array, n);
3103
3598
  }
3104
3599
 
3105
3600
  /**
@@ -3107,16 +3602,23 @@
3107
3602
  * should be inserted into `array` in order to maintain the sort order of the
3108
3603
  * sorted `array`. If `callback` is passed, it will be executed for `value` and
3109
3604
  * each element in `array` to compute their sort ranking. The `callback` is
3110
- * bound to `thisArg` and invoked with one argument; (value). The `callback`
3111
- * argument may also be the name of a property to order by.
3605
+ * bound to `thisArg` and invoked with one argument; (value).
3606
+ *
3607
+ * If a property name is passed for `callback`, the created "_.pluck" style
3608
+ * callback will return the property value of the given element.
3609
+ *
3610
+ * If an object is passed for `callback`, the created "_.where" style callback
3611
+ * will return `true` for elements that have the propeties of the given object,
3612
+ * else `false`.
3112
3613
  *
3113
3614
  * @static
3114
3615
  * @memberOf _
3115
3616
  * @category Arrays
3116
3617
  * @param {Array} array The array to iterate over.
3117
3618
  * @param {Mixed} value The value to evaluate.
3118
- * @param {Function|String} [callback=identity|property] The function called
3119
- * per iteration or property name to order by.
3619
+ * @param {Function|Object|String} [callback=identity] The function called per
3620
+ * iteration. If a property name or object is passed, it will be used to create
3621
+ * a "_.pluck" or "_.where" style callback, respectively.
3120
3622
  * @param {Mixed} [thisArg] The `this` binding of `callback`.
3121
3623
  * @returns {Number} Returns the index at which the value should be inserted
3122
3624
  * into `array`.
@@ -3125,6 +3627,7 @@
3125
3627
  * _.sortedIndex([20, 30, 50], 40);
3126
3628
  * // => 2
3127
3629
  *
3630
+ * // using "_.pluck" callback shorthand
3128
3631
  * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
3129
3632
  * // => 2
3130
3633
  *
@@ -3147,7 +3650,7 @@
3147
3650
  high = array ? array.length : low;
3148
3651
 
3149
3652
  // explicitly reference `identity` for better inlining in Firefox
3150
- callback = callback ? createCallback(callback, thisArg) : identity;
3653
+ callback = callback ? createCallback(callback, thisArg, 1) : identity;
3151
3654
  value = callback(value);
3152
3655
 
3153
3656
  while (low < high) {
@@ -3185,13 +3688,22 @@
3185
3688
  * element of `array` is passed through a callback` before uniqueness is computed.
3186
3689
  * The `callback` is bound to `thisArg` and invoked with three arguments; (value, index, array).
3187
3690
  *
3691
+ * If a property name is passed for `callback`, the created "_.pluck" style
3692
+ * callback will return the property value of the given element.
3693
+ *
3694
+ * If an object is passed for `callback`, the created "_.where" style callback
3695
+ * will return `true` for elements that have the propeties of the given object,
3696
+ * else `false`.
3697
+ *
3188
3698
  * @static
3189
3699
  * @memberOf _
3190
3700
  * @alias unique
3191
3701
  * @category Arrays
3192
3702
  * @param {Array} array The array to process.
3193
3703
  * @param {Boolean} [isSorted=false] A flag to indicate that the `array` is already sorted.
3194
- * @param {Function} [callback=identity] The function called per iteration.
3704
+ * @param {Function|Object|String} [callback=identity] The function called per
3705
+ * iteration. If a property name or object is passed, it will be used to create
3706
+ * a "_.pluck" or "_.where" style callback, respectively.
3195
3707
  * @param {Mixed} [thisArg] The `this` binding of `callback`.
3196
3708
  * @returns {Array} Returns a duplicate-value-free array.
3197
3709
  * @example
@@ -3207,6 +3719,10 @@
3207
3719
  *
3208
3720
  * _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return this.floor(num); }, Math);
3209
3721
  * // => [1, 2, 3]
3722
+ *
3723
+ * // using "_.pluck" callback shorthand
3724
+ * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
3725
+ * // => [{ 'x': 1 }, { 'x': 2 }]
3210
3726
  */
3211
3727
  function uniq(array, isSorted, callback, thisArg) {
3212
3728
  var index = -1,
@@ -3270,7 +3786,7 @@
3270
3786
  function without(array) {
3271
3787
  var index = -1,
3272
3788
  length = array ? array.length : 0,
3273
- contains = cachedContains(arguments, 1, 20),
3789
+ contains = cachedContains(arguments, 1),
3274
3790
  result = [];
3275
3791
 
3276
3792
  while (++index < length) {
@@ -3295,8 +3811,8 @@
3295
3811
  * @returns {Array} Returns a new array of grouped elements.
3296
3812
  * @example
3297
3813
  *
3298
- * _.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
3299
- * // => [['moe', 30, true], ['larry', 40, false], ['curly', 50, false]]
3814
+ * _.zip(['moe', 'larry'], [30, 40], [true, false]);
3815
+ * // => [['moe', 30, true], ['larry', 40, false]]
3300
3816
  */
3301
3817
  function zip(array) {
3302
3818
  var index = -1,
@@ -3374,7 +3890,8 @@
3374
3890
 
3375
3891
  /**
3376
3892
  * Binds methods on `object` to `object`, overwriting the existing method.
3377
- * If no method names are provided, all the function properties of `object`
3893
+ * Method names may be specified as individual arguments or as arrays of method
3894
+ * names. If no method names are provided, all the function properties of `object`
3378
3895
  * will be bound.
3379
3896
  *
3380
3897
  * @static
@@ -3385,17 +3902,17 @@
3385
3902
  * @returns {Object} Returns `object`.
3386
3903
  * @example
3387
3904
  *
3388
- * var buttonView = {
3389
- * 'label': 'lodash',
3390
- * 'onClick': function() { alert('clicked: ' + this.label); }
3905
+ * var view = {
3906
+ * 'label': 'docs',
3907
+ * 'onClick': function() { alert('clicked ' + this.label); }
3391
3908
  * };
3392
3909
  *
3393
- * _.bindAll(buttonView);
3394
- * jQuery('#lodash_button').on('click', buttonView.onClick);
3395
- * // => When the button is clicked, `this.label` will have the correct value
3910
+ * _.bindAll(view);
3911
+ * jQuery('#docs').on('click', view.onClick);
3912
+ * // => alerts 'clicked docs', when the button is clicked
3396
3913
  */
3397
3914
  function bindAll(object) {
3398
- var funcs = arguments,
3915
+ var funcs = concat.apply(arrayRef, arguments),
3399
3916
  index = funcs.length > 1 ? 0 : (funcs = functions(object), -1),
3400
3917
  length = funcs.length;
3401
3918
 
@@ -3447,7 +3964,7 @@
3447
3964
  /**
3448
3965
  * Creates a function that is the composition of the passed functions,
3449
3966
  * where each function consumes the return value of the function that follows.
3450
- * In math terms, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
3967
+ * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
3451
3968
  * Each function is executed with the `this` binding of the composed function.
3452
3969
  *
3453
3970
  * @static
@@ -3457,11 +3974,11 @@
3457
3974
  * @returns {Function} Returns the new composed function.
3458
3975
  * @example
3459
3976
  *
3460
- * var greet = function(name) { return 'hi: ' + name; };
3977
+ * var greet = function(name) { return 'hi ' + name; };
3461
3978
  * var exclaim = function(statement) { return statement + '!'; };
3462
3979
  * var welcome = _.compose(exclaim, greet);
3463
3980
  * welcome('moe');
3464
- * // => 'hi: moe!'
3981
+ * // => 'hi moe!'
3465
3982
  */
3466
3983
  function compose() {
3467
3984
  var funcs = arguments;
@@ -3564,6 +4081,10 @@
3564
4081
  var args = slice(arguments, 1);
3565
4082
  return setTimeout(function() { func.apply(undefined, args); }, 1);
3566
4083
  }
4084
+ // use `setImmediate` if it's available in Node.js
4085
+ if (isV8 && freeModule && typeof setImmediate == 'function') {
4086
+ defer = bind(setImmediate, window);
4087
+ }
3567
4088
 
3568
4089
  /**
3569
4090
  * Creates a function that memoizes the result of `func`. If `resolver` is
@@ -3587,7 +4108,7 @@
3587
4108
  function memoize(func, resolver) {
3588
4109
  var cache = {};
3589
4110
  return function() {
3590
- var key = resolver ? resolver.apply(this, arguments) : arguments[0];
4111
+ var key = (resolver ? resolver.apply(this, arguments) : arguments[0]) + '';
3591
4112
  return hasOwnProperty.call(cache, key)
3592
4113
  ? cache[key]
3593
4114
  : (cache[key] = func.apply(this, arguments));
@@ -3609,11 +4130,11 @@
3609
4130
  * var initialize = _.once(createApplication);
3610
4131
  * initialize();
3611
4132
  * initialize();
3612
- * // Application is only created once.
4133
+ * // `initialize` executes `createApplication` once
3613
4134
  */
3614
4135
  function once(func) {
3615
- var result,
3616
- ran = false;
4136
+ var ran,
4137
+ result;
3617
4138
 
3618
4139
  return function() {
3619
4140
  if (ran) {
@@ -3631,7 +4152,7 @@
3631
4152
  /**
3632
4153
  * Creates a function that, when called, invokes `func` with any additional
3633
4154
  * `partial` arguments prepended to those passed to the new function. This
3634
- * method is similar to `bind`, except it does **not** alter the `this` binding.
4155
+ * method is similar to `_.bind`, except it does **not** alter the `this` binding.
3635
4156
  *
3636
4157
  * @static
3637
4158
  * @memberOf _
@@ -3641,15 +4162,46 @@
3641
4162
  * @returns {Function} Returns the new partially applied function.
3642
4163
  * @example
3643
4164
  *
3644
- * var greet = function(greeting, name) { return greeting + ': ' + name; };
4165
+ * var greet = function(greeting, name) { return greeting + ' ' + name; };
3645
4166
  * var hi = _.partial(greet, 'hi');
3646
4167
  * hi('moe');
3647
- * // => 'hi: moe'
4168
+ * // => 'hi moe'
3648
4169
  */
3649
4170
  function partial(func) {
3650
4171
  return createBound(func, slice(arguments, 1));
3651
4172
  }
3652
4173
 
4174
+ /**
4175
+ * This method is similar to `_.partial`, except that `partial` arguments are
4176
+ * appended to those passed to the new function.
4177
+ *
4178
+ * @static
4179
+ * @memberOf _
4180
+ * @category Functions
4181
+ * @param {Function} func The function to partially apply arguments to.
4182
+ * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
4183
+ * @returns {Function} Returns the new partially applied function.
4184
+ * @example
4185
+ *
4186
+ * var defaultsDeep = _.partialRight(_.merge, _.defaults);
4187
+ *
4188
+ * var options = {
4189
+ * 'variable': 'data',
4190
+ * 'imports': { 'jq': $ }
4191
+ * };
4192
+ *
4193
+ * defaultsDeep(options, _.templateSettings);
4194
+ *
4195
+ * options.variable
4196
+ * // => 'data'
4197
+ *
4198
+ * options.imports
4199
+ * // => { '_': _, 'jq': $ }
4200
+ */
4201
+ function partialRight(func) {
4202
+ return createBound(func, slice(arguments, 1), null, indicatorObject);
4203
+ }
4204
+
3653
4205
  /**
3654
4206
  * Creates a function that, when executed, will only call the `func`
3655
4207
  * function at most once per every `wait` milliseconds. If the throttled
@@ -3783,11 +4335,11 @@
3783
4335
  * }
3784
4336
  * });
3785
4337
  *
3786
- * _.capitalize('larry');
3787
- * // => 'Larry'
4338
+ * _.capitalize('moe');
4339
+ * // => 'Moe'
3788
4340
  *
3789
- * _('curly').capitalize();
3790
- * // => 'Curly'
4341
+ * _('moe').capitalize();
4342
+ * // => 'Moe'
3791
4343
  */
3792
4344
  function mixin(object) {
3793
4345
  forEach(functions(object), function(methodName) {
@@ -3796,9 +4348,7 @@
3796
4348
  lodash.prototype[methodName] = function() {
3797
4349
  var args = [this.__wrapped__];
3798
4350
  push.apply(args, arguments);
3799
-
3800
- var result = func.apply(lodash, args);
3801
- return new lodash(result);
4351
+ return new lodash(func.apply(lodash, args));
3802
4352
  };
3803
4353
  });
3804
4354
  }
@@ -3833,10 +4383,10 @@
3833
4383
  * @example
3834
4384
  *
3835
4385
  * _.random(0, 5);
3836
- * // => a number between 1 and 5
4386
+ * // => a number between 0 and 5
3837
4387
  *
3838
4388
  * _.random(5);
3839
- * // => also a number between 1 and 5
4389
+ * // => also a number between 0 and 5
3840
4390
  */
3841
4391
  function random(min, max) {
3842
4392
  if (min == null && max == null) {
@@ -3851,7 +4401,7 @@
3851
4401
  }
3852
4402
 
3853
4403
  /**
3854
- * Resolves the value of `property` on `object`. If `property` is a function
4404
+ * Resolves the value of `property` on `object`. If `property` is a function,
3855
4405
  * it will be invoked and its result returned, else the property value is
3856
4406
  * returned. If `object` is falsey, then `null` is returned.
3857
4407
  *
@@ -3877,9 +4427,7 @@
3877
4427
  * // => 'nonsense'
3878
4428
  */
3879
4429
  function result(object, property) {
3880
- // based on Backbone's private `getValue` function
3881
- // https://github.com/documentcloud/backbone/blob/0.9.2/backbone.js#L1419-1424
3882
- var value = object ? object[property] : null;
4430
+ var value = object ? object[property] : undefined;
3883
4431
  return isFunction(value) ? object[property]() : value;
3884
4432
  }
3885
4433
 
@@ -3887,12 +4435,17 @@
3887
4435
  * A micro-templating method that handles arbitrary delimiters, preserves
3888
4436
  * whitespace, and correctly escapes quotes within interpolated code.
3889
4437
  *
3890
- * Note: In the development build `_.template` utilizes sourceURLs for easier
4438
+ * Note: In the development build, `_.template` utilizes sourceURLs for easier
3891
4439
  * debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
3892
4440
  *
3893
4441
  * Note: Lo-Dash may be used in Chrome extensions by either creating a `lodash csp`
3894
- * build and avoiding `_.template` use, or loading Lo-Dash in a sandboxed page.
3895
- * See http://developer.chrome.com/trunk/extensions/sandboxingEval.html
4442
+ * build and using precompiled templates, or loading Lo-Dash in a sandbox.
4443
+ *
4444
+ * For more information on precompiling templates see:
4445
+ * http://lodash.com/#custom-builds
4446
+ *
4447
+ * For more information on Chrome extension sandboxes see:
4448
+ * http://developer.chrome.com/stable/extensions/sandboxingEval.html
3896
4449
  *
3897
4450
  * @static
3898
4451
  * @memberOf _
@@ -3916,8 +4469,8 @@
3916
4469
  * // => 'hello moe'
3917
4470
  *
3918
4471
  * var list = '<% _.forEach(people, function(name) { %><li><%= name %></li><% }); %>';
3919
- * _.template(list, { 'people': ['moe', 'larry', 'curly'] });
3920
- * // => '<li>moe</li><li>larry</li><li>curly</li>'
4472
+ * _.template(list, { 'people': ['moe', 'larry'] });
4473
+ * // => '<li>moe</li><li>larry</li>'
3921
4474
  *
3922
4475
  * // using the "escape" delimiter to escape HTML in data property values
3923
4476
  * _.template('<b><%- value %></b>', { 'value': '<script>' });
@@ -3945,11 +4498,11 @@
3945
4498
  * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
3946
4499
  *
3947
4500
  * // using the `variable` option to ensure a with-statement isn't used in the compiled template
3948
- * var compiled = _.template('hello <%= data.name %>!', null, { 'variable': 'data' });
4501
+ * var compiled = _.template('hi <%= data.name %>!', null, { 'variable': 'data' });
3949
4502
  * compiled.source;
3950
4503
  * // => function(data) {
3951
4504
  * var __t, __p = '', __e = _.escape;
3952
- * __p += 'hello ' + ((__t = ( data.name )) == null ? '' : __t) + '!';
4505
+ * __p += 'hi ' + ((__t = ( data.name )) == null ? '' : __t) + '!';
3953
4506
  * return __p;
3954
4507
  * }
3955
4508
  *
@@ -3966,24 +4519,27 @@
3966
4519
  // http://ejohn.org/blog/javascript-micro-templating/
3967
4520
  // and Laura Doktorova's doT.js
3968
4521
  // https://github.com/olado/doT
4522
+ var settings = lodash.templateSettings;
3969
4523
  text || (text = '');
3970
- options || (options = {});
4524
+
4525
+ // avoid missing dependencies when `iteratorTemplate` is not defined
4526
+ options = defaults({}, options, settings);
4527
+
4528
+ var imports = defaults({}, options.imports, settings.imports),
4529
+ importsKeys = keys(imports),
4530
+ importsValues = values(imports);
3971
4531
 
3972
4532
  var isEvaluating,
3973
- result,
3974
- settings = lodash.templateSettings,
3975
4533
  index = 0,
3976
- interpolate = options.interpolate || settings.interpolate || reNoMatch,
3977
- source = "__p += '",
3978
- variable = options.variable || settings.variable,
3979
- hasVariable = variable;
4534
+ interpolate = options.interpolate || reNoMatch,
4535
+ source = "__p += '";
3980
4536
 
3981
4537
  // compile regexp to match each delimiter
3982
4538
  var reDelimiters = RegExp(
3983
- (options.escape || settings.escape || reNoMatch).source + '|' +
4539
+ (options.escape || reNoMatch).source + '|' +
3984
4540
  interpolate.source + '|' +
3985
4541
  (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
3986
- (options.evaluate || settings.evaluate || reNoMatch).source + '|$'
4542
+ (options.evaluate || reNoMatch).source + '|$'
3987
4543
  , 'g');
3988
4544
 
3989
4545
  text.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
@@ -3997,12 +4553,12 @@
3997
4553
  source += "' +\n__e(" + escapeValue + ") +\n'";
3998
4554
  }
3999
4555
  if (evaluateValue) {
4556
+ isEvaluating = true;
4000
4557
  source += "';\n" + evaluateValue + ";\n__p += '";
4001
4558
  }
4002
4559
  if (interpolateValue) {
4003
4560
  source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
4004
4561
  }
4005
- isEvaluating || (isEvaluating = evaluateValue || reComplexDelimiter.test(escapeValue || interpolateValue));
4006
4562
  index = offset + match.length;
4007
4563
 
4008
4564
  // the JS engine embedded in Adobe products requires returning the `match`
@@ -4015,20 +4571,13 @@
4015
4571
  // if `variable` is not specified and the template contains "evaluate"
4016
4572
  // delimiters, wrap a with-statement around the generated code to add the
4017
4573
  // data object to the top of the scope chain
4574
+ var variable = options.variable,
4575
+ hasVariable = variable;
4576
+
4018
4577
  if (!hasVariable) {
4019
4578
  variable = 'obj';
4020
- if (isEvaluating) {
4021
- source = 'with (' + variable + ') {\n' + source + '\n}\n';
4022
- }
4023
- else {
4024
- // avoid a with-statement by prepending data object references to property names
4025
- var reDoubleVariable = RegExp('(\\(\\s*)' + variable + '\\.' + variable + '\\b', 'g');
4026
- source = source
4027
- .replace(reInsertVariable, '$&' + variable + '.')
4028
- .replace(reDoubleVariable, '$1__d');
4029
- }
4579
+ source = 'with (' + variable + ') {\n' + source + '\n}\n';
4030
4580
  }
4031
-
4032
4581
  // cleanup code by stripping empty strings
4033
4582
  source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
4034
4583
  .replace(reEmptyStringMiddle, '$1')
@@ -4041,24 +4590,23 @@
4041
4590
  (isEvaluating
4042
4591
  ? ', __j = Array.prototype.join;\n' +
4043
4592
  "function print() { __p += __j.call(arguments, '') }\n"
4044
- : (hasVariable ? '' : ', __d = ' + variable + '.' + variable + ' || ' + variable) + ';\n'
4593
+ : ';\n'
4045
4594
  ) +
4046
4595
  source +
4047
4596
  'return __p\n}';
4048
4597
 
4049
- // use a sourceURL for easier debugging
4598
+ // Use a sourceURL for easier debugging and wrap in a multi-line comment to
4599
+ // avoid issues with Narwhal, IE conditional compilation, and the JS engine
4600
+ // embedded in Adobe products.
4050
4601
  // http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
4051
- var sourceURL = useSourceURL
4052
- ? '\n//@ sourceURL=' + (options.sourceURL || '/lodash/template/source[' + (templateCounter++) + ']')
4053
- : '';
4602
+ var sourceURL = '\n/*\n//@ sourceURL=' + (options.sourceURL || '/lodash/template/source[' + (templateCounter++) + ']') + '\n*/';
4054
4603
 
4055
4604
  try {
4056
- result = Function('_', 'return ' + source + sourceURL)(lodash);
4605
+ var result = Function(importsKeys, 'return ' + source + sourceURL).apply(undefined, importsValues);
4057
4606
  } catch(e) {
4058
4607
  e.source = source;
4059
4608
  throw e;
4060
4609
  }
4061
-
4062
4610
  if (data) {
4063
4611
  return result(data);
4064
4612
  }
@@ -4105,7 +4653,7 @@
4105
4653
 
4106
4654
  /**
4107
4655
  * The opposite of `_.escape`, this method converts the HTML entities
4108
- * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#x27;` in `string` to their
4656
+ * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to their
4109
4657
  * corresponding characters.
4110
4658
  *
4111
4659
  * @static
@@ -4139,7 +4687,8 @@
4139
4687
  * // => '105'
4140
4688
  */
4141
4689
  function uniqueId(prefix) {
4142
- return (prefix == null ? '' : prefix + '') + (++idCounter);
4690
+ var id = ++idCounter;
4691
+ return (prefix == null ? '' : prefix + '') + id;
4143
4692
  }
4144
4693
 
4145
4694
  /*--------------------------------------------------------------------------*/
@@ -4157,13 +4706,13 @@
4157
4706
  * @returns {Mixed} Returns `value`.
4158
4707
  * @example
4159
4708
  *
4160
- * _.chain([1, 2, 3, 200])
4709
+ * _([1, 2, 3, 4])
4161
4710
  * .filter(function(num) { return num % 2 == 0; })
4162
4711
  * .tap(alert)
4163
4712
  * .map(function(num) { return num * num; })
4164
4713
  * .value();
4165
- * // => // [2, 200] (alerted)
4166
- * // => [4, 40000]
4714
+ * // => // [2, 4] (alerted)
4715
+ * // => [4, 16]
4167
4716
  */
4168
4717
  function tap(value, interceptor) {
4169
4718
  interceptor(value);
@@ -4208,6 +4757,7 @@
4208
4757
  // add functions that return wrapped values when chaining
4209
4758
  lodash.after = after;
4210
4759
  lodash.assign = assign;
4760
+ lodash.at = at;
4211
4761
  lodash.bind = bind;
4212
4762
  lodash.bindAll = bindAll;
4213
4763
  lodash.bindKey = bindKey;
@@ -4241,6 +4791,7 @@
4241
4791
  lodash.once = once;
4242
4792
  lodash.pairs = pairs;
4243
4793
  lodash.partial = partial;
4794
+ lodash.partialRight = partialRight;
4244
4795
  lodash.pick = pick;
4245
4796
  lodash.pluck = pluck;
4246
4797
  lodash.range = range;
@@ -4347,9 +4898,11 @@
4347
4898
 
4348
4899
  forOwn(lodash, function(func, methodName) {
4349
4900
  if (!lodash.prototype[methodName]) {
4350
- lodash.prototype[methodName]= function(n, guard) {
4351
- var result = func(this.__wrapped__, n, guard);
4352
- return (n == null || guard) ? result : new lodash(result);
4901
+ lodash.prototype[methodName]= function(callback, thisArg) {
4902
+ var result = func(this.__wrapped__, callback, thisArg);
4903
+ return callback == null || (thisArg && typeof callback != 'function')
4904
+ ? result
4905
+ : new lodash(result);
4353
4906
  };
4354
4907
  }
4355
4908
  });
@@ -4363,7 +4916,7 @@
4363
4916
  * @memberOf _
4364
4917
  * @type String
4365
4918
  */
4366
- lodash.VERSION = '1.0.0-rc.3';
4919
+ lodash.VERSION = '1.0.1';
4367
4920
 
4368
4921
  // add "Chaining" functions to the wrapper
4369
4922
  lodash.prototype.toString = wrapperToString;
@@ -4391,34 +4944,10 @@
4391
4944
  each(['concat', 'slice', 'splice'], function(methodName) {
4392
4945
  var func = arrayRef[methodName];
4393
4946
  lodash.prototype[methodName] = function() {
4394
- var result = func.apply(this.__wrapped__, arguments);
4395
- return new lodash(result);
4947
+ return new lodash(func.apply(this.__wrapped__, arguments));
4396
4948
  };
4397
4949
  });
4398
4950
 
4399
- // avoid array-like object bugs with `Array#shift` and `Array#splice`
4400
- // in Firefox < 10 and IE < 9
4401
- if (hasObjectSpliceBug) {
4402
- each(['pop', 'shift', 'splice'], function(methodName) {
4403
- var func = arrayRef[methodName],
4404
- isSplice = methodName == 'splice';
4405
-
4406
- lodash.prototype[methodName] = function() {
4407
- var value = this.__wrapped__,
4408
- result = func.apply(value, arguments);
4409
-
4410
- if (value.length === 0) {
4411
- delete value[0];
4412
- }
4413
- return isSplice ? new lodash(result) : result;
4414
- };
4415
- });
4416
- }
4417
-
4418
- // add pseudo private property to be used and removed during the build process
4419
- lodash._each = each;
4420
- lodash._iteratorTemplate = iteratorTemplate;
4421
-
4422
4951
  /*--------------------------------------------------------------------------*/
4423
4952
 
4424
4953
  // expose Lo-Dash
@@ -4439,8 +4968,8 @@
4439
4968
  // check for `exports` after `define` in case a build optimizer adds an `exports` object
4440
4969
  else if (freeExports) {
4441
4970
  // in Node.js or RingoJS v0.8.0+
4442
- if (typeof module == 'object' && module && module.exports == freeExports) {
4443
- (module.exports = lodash)._ = lodash;
4971
+ if (freeModule) {
4972
+ (freeModule.exports = lodash)._ = lodash;
4444
4973
  }
4445
4974
  // in Narwhal or RingoJS v0.7.0-
4446
4975
  else {