lodash-rails 0.10.0 → 1.0.0.rc.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 0.10.0 (lodash, lodash.min)
21
+ * Lo-Dash 1.0.0-rc.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 = "0.10.0"
3
+ VERSION = "1.0.0.rc.1"
4
4
  end
5
5
  end
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lo-Dash 0.10.0 <http://lodash.com>
2
+ * Lo-Dash 1.0.0-rc.1 <http://lodash.com>
3
3
  * (c) 2012 John-David Dalton <http://allyoucanleet.com/>
4
4
  * Based on Underscore.js 1.4.2 <http://underscorejs.org>
5
5
  * (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
@@ -92,7 +92,6 @@
92
92
  hasOwnProperty = objectRef.hasOwnProperty,
93
93
  push = arrayRef.push,
94
94
  propertyIsEnumerable = objectRef.propertyIsEnumerable,
95
- slice = arrayRef.slice,
96
95
  toString = objectRef.toString;
97
96
 
98
97
  /* Native method shortcuts for methods with the same name as other `lodash` methods */
@@ -116,6 +115,17 @@
116
115
  regexpClass = '[object RegExp]',
117
116
  stringClass = '[object String]';
118
117
 
118
+ /** Detect various environments */
119
+ var isFirefox = !/1/.test(Function('1')),
120
+ isIeOpera = !!window.attachEvent,
121
+ isV8 = nativeBind && !/\n|true/.test(nativeBind + isIeOpera);
122
+
123
+ /* Detect if `Function#bind` exists and is inferred to be fast (all but V8) */
124
+ var isBindFast = nativeBind && !isV8;
125
+
126
+ /* Detect if `Object.keys` exists and is inferred to be fast (IE, Opera, V8) */
127
+ var isKeysFast = nativeKeys && (isIeOpera || isV8);
128
+
119
129
  /**
120
130
  * Detect the JScript [[DontEnum]] bug:
121
131
  *
@@ -157,9 +167,6 @@
157
167
  /** Detect if an `arguments` object's [[Class]] is unresolvable (Firefox < 4, IE < 9) */
158
168
  var noArgsClass = !isArguments(arguments);
159
169
 
160
- /** Detect if `Array#slice` cannot be used to convert strings to arrays (Opera < 10.52) */
161
- var noArraySliceOnStrings = slice.call('x')[0] != 'x';
162
-
163
170
  /**
164
171
  * Detect lack of support for accessing string characters by index:
165
172
  *
@@ -174,20 +181,14 @@
174
181
  * a string without a `toString` property value of `typeof` "function".
175
182
  */
176
183
  try {
177
- var noNodeClass = ({ 'toString': 0 } + '', toString.call(window.document || 0) == objectClass);
184
+ var noNodeClass = ({ 'toString': 0 } + '', toString.call(document) == objectClass);
178
185
  } catch(e) { }
179
186
 
180
- /* Detect if `Function#bind` exists and is inferred to be fast (all but V8) */
181
- var isBindFast = nativeBind && /\n|Opera/.test(nativeBind + toString.call(window.opera));
182
-
183
- /* Detect if `Object.keys` exists and is inferred to be fast (IE, Opera, V8) */
184
- var isKeysFast = nativeKeys && /^.+$|true/.test(nativeKeys + !!window.attachEvent);
185
-
186
187
  /**
187
188
  * Detect if sourceURL syntax is usable without erroring:
188
189
  *
189
- * The JS engine in Adobe products, like InDesign, will throw a syntax error
190
- * when it encounters a single line comment beginning with the `@` symbol.
190
+ * The JS engine embedded in Adobe products will throw a syntax error when
191
+ * it encounters a single line comment beginning with the `@` symbol.
191
192
  *
192
193
  * The JS engine in Narwhal will generate the function `function anonymous(){//}`
193
194
  * and throw a syntax error.
@@ -197,15 +198,26 @@
197
198
  * http://msdn.microsoft.com/en-us/library/121hztk3(v=vs.94).aspx
198
199
  */
199
200
  try {
200
- var useSourceURL = (Function('//@')(), !window.attachEvent);
201
+ var useSourceURL = (Function('//@')(), !isIeOpera);
201
202
  } catch(e) { }
202
203
 
203
204
  /** Used to identify object classifications that `_.clone` supports */
204
205
  var cloneableClasses = {};
205
- cloneableClasses[argsClass] = cloneableClasses[funcClass] = false;
206
- cloneableClasses[arrayClass] = cloneableClasses[boolClass] = cloneableClasses[dateClass] =
207
- cloneableClasses[numberClass] = cloneableClasses[objectClass] = cloneableClasses[regexpClass] =
208
- cloneableClasses[stringClass] = true;
206
+ cloneableClasses[funcClass] = false;
207
+ cloneableClasses[argsClass] = cloneableClasses[arrayClass] =
208
+ cloneableClasses[boolClass] = cloneableClasses[dateClass] =
209
+ cloneableClasses[numberClass] = cloneableClasses[objectClass] =
210
+ cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true;
211
+
212
+ /** Used to lookup a built-in constructor by [[Class]] */
213
+ var ctorByClass = {};
214
+ ctorByClass[arrayClass] = Array;
215
+ ctorByClass[boolClass] = Boolean;
216
+ ctorByClass[dateClass] = Date;
217
+ ctorByClass[objectClass] = Object;
218
+ ctorByClass[numberClass] = Number;
219
+ ctorByClass[regexpClass] = RegExp;
220
+ ctorByClass[stringClass] = String;
209
221
 
210
222
  /** Used to determine if values are of the language type Object */
211
223
  var objectTypes = {
@@ -240,8 +252,8 @@
240
252
  * @returns {Object} Returns a `lodash` instance.
241
253
  */
242
254
  function lodash(value) {
243
- // exit early if already wrapped
244
- if (value && value.__wrapped__) {
255
+ // exit early if already wrapped, even if wrapped by a different `lodash` constructor
256
+ if (value && typeof value == 'object' && value.__wrapped__) {
245
257
  return value;
246
258
  }
247
259
  // allow invoking `lodash` without the `new` operator
@@ -301,6 +313,25 @@
301
313
 
302
314
  /*--------------------------------------------------------------------------*/
303
315
 
316
+ /**
317
+ * Creates a function from the given `args` and `body` strings.
318
+ *
319
+ * @private
320
+ * @param {String} args The comma separated function arguments.
321
+ * @param {String} body The function body.
322
+ * @returns {Function} The new function.
323
+ */
324
+ function createFunction(args, body) {
325
+ // the newline, in `'\n}'`, is required to avoid errors if `body` ends
326
+ // with a single line comment
327
+ return window.eval('(function(' + args + ') {' + body + '\n})');
328
+ }
329
+ // use `eval` to avoid Firefox's unoptimized `Function` constructor
330
+ // http://bugzil.la/804933
331
+ if (isIeOpera || isV8 || !isFirefox) {
332
+ createFunction = Function;
333
+ }
334
+
304
335
  /**
305
336
  * The template used to create iterator functions.
306
337
  *
@@ -310,10 +341,10 @@
310
341
  */
311
342
  var iteratorTemplate = template(
312
343
  // conditional strict mode
313
- '<% if (obj.useStrict) { %>\'use strict\';\n<% } %>' +
344
+ "<% if (obj.useStrict) { %>'use strict';\n<% } %>" +
314
345
 
315
346
  // the `iteratee` may be reassigned by the `top` snippet
316
- 'var index, value, iteratee = <%= firstArg %>, ' +
347
+ 'var index, iteratee = <%= firstArg %>, ' +
317
348
  // assign the `result` variable an initial value
318
349
  'result = <%= firstArg %>;\n' +
319
350
  // exit early if the first argument is falsey
@@ -324,18 +355,17 @@
324
355
  // array-like iteration:
325
356
  '<% if (arrayLoop) { %>' +
326
357
  'var length = iteratee.length; index = -1;\n' +
327
- 'if (typeof length == \'number\') {' +
358
+ "if (typeof length == 'number') {" +
328
359
 
329
360
  // add support for accessing string characters by index if needed
330
361
  ' <% if (noCharByIndex) { %>\n' +
331
362
  ' if (isString(iteratee)) {\n' +
332
- ' iteratee = iteratee.split(\'\')\n' +
363
+ " iteratee = iteratee.split('')\n" +
333
364
  ' }' +
334
365
  ' <% } %>\n' +
335
366
 
336
367
  // iterate over the array-like value
337
368
  ' while (++index < length) {\n' +
338
- ' value = iteratee[index];\n' +
339
369
  ' <%= arrayLoop %>\n' +
340
370
  ' }\n' +
341
371
  '}\n' +
@@ -347,7 +377,7 @@
347
377
  ' var length = iteratee.length; index = -1;\n' +
348
378
  ' if (length && isArguments(iteratee)) {\n' +
349
379
  ' while (++index < length) {\n' +
350
- ' value = iteratee[index += \'\'];\n' +
380
+ " index += '';\n" +
351
381
  ' <%= objectLoop %>\n' +
352
382
  ' }\n' +
353
383
  ' } else {' +
@@ -360,8 +390,8 @@
360
390
  // the the `prototype` property of functions regardless of its
361
391
  // [[Enumerable]] value.
362
392
  ' <% if (!hasDontEnumBug) { %>\n' +
363
- ' var skipProto = typeof iteratee == \'function\' && \n' +
364
- ' propertyIsEnumerable.call(iteratee, \'prototype\');\n' +
393
+ " var skipProto = typeof iteratee == 'function' && \n" +
394
+ " propertyIsEnumerable.call(iteratee, 'prototype');\n" +
365
395
  ' <% } %>' +
366
396
 
367
397
  // iterate own properties using `Object.keys` if it's fast
@@ -371,8 +401,7 @@
371
401
  ' length = ownProps.length;\n\n' +
372
402
  ' while (++ownIndex < length) {\n' +
373
403
  ' index = ownProps[ownIndex];\n' +
374
- ' <% if (!hasDontEnumBug) { %>if (!(skipProto && index == \'prototype\')) {\n <% } %>' +
375
- ' value = iteratee[index];\n' +
404
+ " <% if (!hasDontEnumBug) { %>if (!(skipProto && index == 'prototype')) {\n <% } %>" +
376
405
  ' <%= objectLoop %>\n' +
377
406
  ' <% if (!hasDontEnumBug) { %>}\n<% } %>' +
378
407
  ' }' +
@@ -381,12 +410,11 @@
381
410
  ' <% } else { %>\n' +
382
411
  ' for (index in iteratee) {<%' +
383
412
  ' if (!hasDontEnumBug || useHas) { %>\n if (<%' +
384
- ' if (!hasDontEnumBug) { %>!(skipProto && index == \'prototype\')<% }' +
413
+ " if (!hasDontEnumBug) { %>!(skipProto && index == 'prototype')<% }" +
385
414
  ' if (!hasDontEnumBug && useHas) { %> && <% }' +
386
415
  ' if (useHas) { %>hasOwnProperty.call(iteratee, index)<% }' +
387
416
  ' %>) {' +
388
417
  ' <% } %>\n' +
389
- ' value = iteratee[index];\n' +
390
418
  ' <%= objectLoop %>;' +
391
419
  ' <% if (!hasDontEnumBug || useHas) { %>\n }<% } %>\n' +
392
420
  ' }' +
@@ -399,12 +427,11 @@
399
427
  ' <% if (hasDontEnumBug) { %>\n\n' +
400
428
  ' var ctor = iteratee.constructor;\n' +
401
429
  ' <% for (var k = 0; k < 7; k++) { %>\n' +
402
- ' index = \'<%= shadowed[k] %>\';\n' +
430
+ " index = '<%= shadowed[k] %>';\n" +
403
431
  ' if (<%' +
404
- ' if (shadowed[k] == \'constructor\') {' +
432
+ " if (shadowed[k] == 'constructor') {" +
405
433
  ' %>!(ctor && ctor.prototype === iteratee) && <%' +
406
434
  ' } %>hasOwnProperty.call(iteratee, index)) {\n' +
407
- ' value = iteratee[index];\n' +
408
435
  ' <%= objectLoop %>\n' +
409
436
  ' }' +
410
437
  ' <% } %>' +
@@ -421,9 +448,9 @@
421
448
  var assignIteratorOptions = {
422
449
  'args': 'object, source, guard',
423
450
  'top':
424
- 'for (var argsIndex = 1, argsLength = typeof guard == \'number\' ? 2 : arguments.length; argsIndex < argsLength; argsIndex++) {\n' +
451
+ "for (var argsIndex = 1, argsLength = typeof guard == 'number' ? 2 : arguments.length; argsIndex < argsLength; argsIndex++) {\n" +
425
452
  ' if ((iteratee = arguments[argsIndex])) {',
426
- 'objectLoop': 'result[index] = value',
453
+ 'objectLoop': 'result[index] = iteratee[index]',
427
454
  'bottom': ' }\n}'
428
455
  };
429
456
 
@@ -432,9 +459,9 @@
432
459
  */
433
460
  var forEachIteratorOptions = {
434
461
  'args': 'collection, callback, thisArg',
435
- 'top': 'callback = createCallback(callback, thisArg)',
436
- 'arrayLoop': 'if (callback(value, index, collection) === false) return result',
437
- 'objectLoop': 'if (callback(value, index, collection) === false) return result'
462
+ 'top': "callback = callback && typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg)",
463
+ 'arrayLoop': 'if (callback(iteratee[index], index, collection) === false) return result',
464
+ 'objectLoop': 'if (callback(iteratee[index], index, collection) === false) return result'
438
465
  };
439
466
 
440
467
  /** Reusable iterator options for `forIn` and `forOwn` */
@@ -512,10 +539,10 @@
512
539
  // ensure a stable sort in V8 and other engines
513
540
  // http://code.google.com/p/v8/issues/detail?id=90
514
541
  if (a !== b) {
515
- if (a > b || a === undefined) {
542
+ if (a > b || typeof a == 'undefined') {
516
543
  return 1;
517
544
  }
518
- if (a < b || b === undefined) {
545
+ if (a < b || typeof b == 'undefined') {
519
546
  return -1;
520
547
  }
521
548
  }
@@ -557,20 +584,19 @@
557
584
  }
558
585
  if (partialArgs.length) {
559
586
  args = args.length
560
- ? partialArgs.concat(slice.call(args))
587
+ ? partialArgs.concat(slice(args))
561
588
  : partialArgs;
562
589
  }
563
590
  if (this instanceof bound) {
564
- // get `func` instance if `bound` is invoked in a `new` expression
591
+ // ensure `new bound` is an instance of `bound` and `func`
565
592
  noop.prototype = func.prototype;
566
593
  thisBinding = new noop;
594
+ noop.prototype = null;
567
595
 
568
596
  // mimic the constructor's `return` behavior
569
597
  // http://es5.github.com/#x13.2.2
570
598
  var result = func.apply(thisBinding, args);
571
- return isObject(result)
572
- ? result
573
- : thisBinding
599
+ return isObject(result) ? result : thisBinding;
574
600
  }
575
601
  return func.apply(thisBinding, args);
576
602
  }
@@ -596,7 +622,7 @@
596
622
  return object[func];
597
623
  };
598
624
  }
599
- if (thisArg !== undefined) {
625
+ if (typeof thisArg != 'undefined') {
600
626
  return function(value, index, object) {
601
627
  return func.call(thisArg, value, index, object);
602
628
  };
@@ -642,7 +668,7 @@
642
668
  data.firstArg = /^[^,]+/.exec(args)[0];
643
669
 
644
670
  // create the function factory
645
- var factory = Function(
671
+ var factory = createFunction(
646
672
  'createCallback, hasOwnProperty, isArguments, isString, objectTypes, ' +
647
673
  'nativeKeys, propertyIsEnumerable',
648
674
  'return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}'
@@ -677,6 +703,19 @@
677
703
  return htmlEscapes[match];
678
704
  }
679
705
 
706
+ /**
707
+ * Checks if `value` is a DOM node in IE < 9.
708
+ *
709
+ * @private
710
+ * @param {Mixed} value The value to check.
711
+ * @returns {Boolean} Returns `true` if the `value` is a DOM node, else `false`.
712
+ */
713
+ function isNode(value) {
714
+ // IE < 9 presents DOM nodes as `Object` objects except they have `toString`
715
+ // methods that are `typeof` "string" and still can coerce nodes to strings
716
+ return typeof value.toString != 'function' && typeof (value + '') == 'string';
717
+ }
718
+
680
719
  /**
681
720
  * A no-operation function.
682
721
  *
@@ -686,6 +725,34 @@
686
725
  // no operation performed
687
726
  }
688
727
 
728
+ /**
729
+ * Slices the `collection` from the `start` index up to, but not including,
730
+ * the `end` index.
731
+ *
732
+ * Note: This function is used, instead of `Array#slice`, to support node lists
733
+ * in IE < 9 and to ensure dense arrays are returned.
734
+ *
735
+ * @private
736
+ * @param {Array|Object|String} collection The collection to slice.
737
+ * @param {Number} start The start index.
738
+ * @param {Number} end The end index.
739
+ * @returns {Array} Returns the new array.
740
+ */
741
+ function slice(array, start, end) {
742
+ start || (start = 0);
743
+ if (typeof end == 'undefined') {
744
+ end = array ? array.length : 0;
745
+ }
746
+ var index = -1,
747
+ length = end - start || 0,
748
+ result = Array(length < 0 ? 0 : length);
749
+
750
+ while (++index < length) {
751
+ result[index] = array[start + index];
752
+ }
753
+ return result;
754
+ }
755
+
689
756
  /**
690
757
  * Used by `unescape` to convert HTML entities to characters.
691
758
  *
@@ -754,7 +821,7 @@
754
821
  * @memberOf _
755
822
  * @category Objects
756
823
  * @param {Object} object The object to iterate over.
757
- * @param {Function} callback The function called per iteration.
824
+ * @param {Function} [callback=identity] The function called per iteration.
758
825
  * @param {Mixed} [thisArg] The `this` binding of `callback`.
759
826
  * @returns {Object} Returns `object`.
760
827
  * @example
@@ -786,7 +853,7 @@
786
853
  * @memberOf _
787
854
  * @category Objects
788
855
  * @param {Object} object The object to iterate over.
789
- * @param {Function} callback The function called per iteration.
856
+ * @param {Function} [callback=identity] The function called per iteration.
790
857
  * @param {Mixed} [thisArg] The `this` binding of `callback`.
791
858
  * @returns {Object} Returns `object`.
792
859
  * @example
@@ -814,12 +881,9 @@
814
881
  if (!(value && typeof value == 'object') || isArguments(value)) {
815
882
  return result;
816
883
  }
817
- // IE < 9 presents DOM nodes as `Object` objects except they have `toString`
818
- // methods that are `typeof` "string" and still can coerce nodes to strings.
819
- // Also check that the constructor is `Object` (i.e. `Object instanceof Object`)
884
+ // check that the constructor is `Object` (i.e. `Object instanceof Object`)
820
885
  var ctor = value.constructor;
821
- if ((!noNodeClass || !(typeof value.toString != 'function' && typeof (value + '') == 'string')) &&
822
- (!isFunction(ctor) || ctor instanceof ctor)) {
886
+ if ((!isFunction(ctor) && (!noNodeClass || !isNode(value))) || ctor instanceof ctor) {
823
887
  // IE < 9 iterates inherited properties before own properties. If the first
824
888
  // iterated property is an object's own property then there are no inherited
825
889
  // enumerable properties.
@@ -880,9 +944,13 @@
880
944
 
881
945
  /**
882
946
  * Creates a clone of `value`. If `deep` is `true`, all nested objects will
883
- * also be cloned otherwise they will be assigned by reference. Functions, DOM
884
- * nodes, `arguments` objects, and objects created by constructors other than
885
- * `Object` are **not** cloned.
947
+ * also be cloned, otherwise they will be assigned by reference. Functions and
948
+ * DOM nodes are **not** cloned. The enumerable properties of `arguments` objects
949
+ * and objects created by constructors other than `Object` are cloned to plain
950
+ * `Object` objects.
951
+ *
952
+ * Note: Lo-Dash's deep clone functionality is loosely based on the structured clone algorithm.
953
+ * See http://www.w3.org/TR/html5/common-dom-interfaces.html#internal-structured-cloning-algorithm.
886
954
  *
887
955
  * @static
888
956
  * @memberOf _
@@ -911,7 +979,7 @@
911
979
  * // => true
912
980
  *
913
981
  * var deep = _.clone(stooges, true);
914
- * shallow[0] === stooges[0];
982
+ * deep[0] === stooges[0];
915
983
  * // => false
916
984
  */
917
985
  function clone(value, deep, guard, stackA, stackB) {
@@ -924,23 +992,19 @@
924
992
  // inspect [[Class]]
925
993
  var isObj = isObject(value);
926
994
  if (isObj) {
927
- // don't clone `arguments` objects, functions, or non-object Objects
928
995
  var className = toString.call(value);
929
- if (!cloneableClasses[className] || (noArgsClass && isArguments(value))) {
996
+ if (!cloneableClasses[className] || (noNodeClass && isNode(value))) {
930
997
  return value;
931
998
  }
932
- var isArr = className == arrayClass;
933
- isObj = isArr || (className == objectClass ? isPlainObject(value) : isObj);
999
+ var isArr = isArray(value);
934
1000
  }
935
1001
  // shallow clone
936
1002
  if (!isObj || !deep) {
937
- // don't clone functions
938
1003
  return isObj
939
- ? (isArr ? slice.call(value) : assign({}, value))
1004
+ ? (isArr ? slice(value) : assign({}, value))
940
1005
  : value;
941
1006
  }
942
-
943
- var ctor = value.constructor;
1007
+ var ctor = ctorByClass[className];
944
1008
  switch (className) {
945
1009
  case boolClass:
946
1010
  case dateClass:
@@ -976,6 +1040,15 @@
976
1040
  result[key] = clone(objValue, deep, null, stackA, stackB);
977
1041
  });
978
1042
 
1043
+ // add array properties assigned by `RegExp#exec`
1044
+ if (isArr) {
1045
+ if (hasOwnProperty.call(value, 'index')) {
1046
+ result.index = value.index;
1047
+ }
1048
+ if (hasOwnProperty.call(value, 'input')) {
1049
+ result.input = value.input;
1050
+ }
1051
+ }
979
1052
  return result;
980
1053
  }
981
1054
 
@@ -1211,8 +1284,16 @@
1211
1284
  return a === b;
1212
1285
  }
1213
1286
  // compare [[Class]] names
1214
- var className = toString.call(a);
1215
- if (className != toString.call(b)) {
1287
+ var className = toString.call(a),
1288
+ otherName = toString.call(b);
1289
+
1290
+ if (className == argsClass) {
1291
+ className = objectClass;
1292
+ }
1293
+ if (otherName == argsClass) {
1294
+ otherName = objectClass;
1295
+ }
1296
+ if (className != otherName) {
1216
1297
  return false;
1217
1298
  }
1218
1299
  switch (className) {
@@ -1235,24 +1316,19 @@
1235
1316
  // treat string primitives and their corresponding object instances as equal
1236
1317
  return a == b + '';
1237
1318
  }
1238
- // exit early, in older browsers, if `a` is array-like but not `b`
1239
- var isArr = className == arrayClass || className == argsClass;
1240
- if (noArgsClass && !isArr && (isArr = isArguments(a)) && !isArguments(b)) {
1241
- return false;
1242
- }
1319
+ var isArr = className == arrayClass;
1243
1320
  if (!isArr) {
1244
1321
  // unwrap any `lodash` wrapped values
1245
1322
  if (a.__wrapped__ || b.__wrapped__) {
1246
1323
  return isEqual(a.__wrapped__ || a, b.__wrapped__ || b);
1247
1324
  }
1248
1325
  // exit for functions and DOM nodes
1249
- if (className != objectClass || (noNodeClass && (
1250
- (typeof a.toString != 'function' && typeof (a + '') == 'string') ||
1251
- (typeof b.toString != 'function' && typeof (b + '') == 'string')))) {
1326
+ if (className != objectClass || (noNodeClass && (isNode(a) || isNode(b)))) {
1252
1327
  return false;
1253
1328
  }
1254
- var ctorA = a.constructor,
1255
- ctorB = b.constructor;
1329
+ // in older versions of Opera, `arguments` objects have `Array` constructors
1330
+ var ctorA = noArgsClass && isArguments(a) ? Object : a.constructor,
1331
+ ctorB = noArgsClass && isArguments(b) ? Object : b.constructor;
1256
1332
 
1257
1333
  // non `Object` object instances with different constructors are not equal
1258
1334
  if (ctorA != ctorB && !(
@@ -1274,7 +1350,6 @@
1274
1350
  return stackB[length] == b;
1275
1351
  }
1276
1352
  }
1277
-
1278
1353
  var index = -1,
1279
1354
  result = true,
1280
1355
  size = 0;
@@ -1299,38 +1374,27 @@
1299
1374
  }
1300
1375
  return result;
1301
1376
  }
1302
- // deep compare objects
1303
- for (var key in a) {
1377
+ // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys`
1378
+ // which, in this case, is more costly
1379
+ forIn(a, function(value, key, a) {
1304
1380
  if (hasOwnProperty.call(a, key)) {
1305
1381
  // count the number of properties.
1306
1382
  size++;
1307
1383
  // deep compare each property value.
1308
- if (!(hasOwnProperty.call(b, key) && isEqual(a[key], b[key], stackA, stackB))) {
1309
- return false;
1310
- }
1384
+ return (result = hasOwnProperty.call(b, key) && isEqual(value, b[key], stackA, stackB));
1311
1385
  }
1312
- }
1313
- // ensure both objects have the same number of properties
1314
- for (key in b) {
1315
- // The JS engine in Adobe products, like InDesign, has a bug that causes
1316
- // `!size--` to throw an error so it must be wrapped in parentheses.
1317
- // https://github.com/documentcloud/underscore/issues/355
1318
- if (hasOwnProperty.call(b, key) && !(size--)) {
1319
- // `size` will be `-1` if `b` has more properties than `a`
1320
- return false;
1321
- }
1322
- }
1323
- // handle JScript [[DontEnum]] bug
1324
- if (hasDontEnumBug) {
1325
- while (++index < 7) {
1326
- key = shadowed[index];
1327
- if (hasOwnProperty.call(a, key) &&
1328
- !(hasOwnProperty.call(b, key) && isEqual(a[key], b[key], stackA, stackB))) {
1329
- return false;
1386
+ });
1387
+
1388
+ if (result) {
1389
+ // ensure both objects have the same number of properties
1390
+ forIn(b, function(value, key, b) {
1391
+ if (hasOwnProperty.call(b, key)) {
1392
+ // `size` will be `-1` if `b` has more properties than `a`
1393
+ return (result = --size > -1);
1330
1394
  }
1331
- }
1395
+ });
1332
1396
  }
1333
- return true;
1397
+ return result;
1334
1398
  }
1335
1399
 
1336
1400
  /**
@@ -1339,7 +1403,6 @@
1339
1403
  * Note: This is not the same as native `isFinite`, which will return true for
1340
1404
  * booleans and empty strings. See http://es5.github.com/#x15.1.2.5.
1341
1405
  *
1342
- * @deprecated
1343
1406
  * @static
1344
1407
  * @memberOf _
1345
1408
  * @category Objects
@@ -1420,10 +1483,9 @@
1420
1483
  /**
1421
1484
  * Checks if `value` is `NaN`.
1422
1485
  *
1423
- * Note: This is not the same as native `isNaN`, which will return true for
1486
+ * Note: This is not the same as native `isNaN`, which will return `true` for
1424
1487
  * `undefined` and other values. See http://es5.github.com/#x15.1.2.4.
1425
1488
  *
1426
- * @deprecated
1427
1489
  * @static
1428
1490
  * @memberOf _
1429
1491
  * @category Objects
@@ -1446,13 +1508,12 @@
1446
1508
  function isNaN(value) {
1447
1509
  // `NaN` as a primitive is the only value that is not equal to itself
1448
1510
  // (perform the [[Class]] check first to avoid errors with some host objects in IE)
1449
- return toString.call(value) == numberClass && value != +value
1511
+ return isNumber(value) && value != +value
1450
1512
  }
1451
1513
 
1452
1514
  /**
1453
1515
  * Checks if `value` is `null`.
1454
1516
  *
1455
- * @deprecated
1456
1517
  * @static
1457
1518
  * @memberOf _
1458
1519
  * @category Objects
@@ -1484,7 +1545,7 @@
1484
1545
  * // => true
1485
1546
  */
1486
1547
  function isNumber(value) {
1487
- return toString.call(value) == numberClass;
1548
+ return typeof value == 'number' || toString.call(value) == numberClass;
1488
1549
  }
1489
1550
 
1490
1551
  /**
@@ -1554,13 +1615,12 @@
1554
1615
  * // => true
1555
1616
  */
1556
1617
  function isString(value) {
1557
- return toString.call(value) == stringClass;
1618
+ return typeof value == 'string' || toString.call(value) == stringClass;
1558
1619
  }
1559
1620
 
1560
1621
  /**
1561
1622
  * Checks if `value` is `undefined`.
1562
1623
  *
1563
- * @deprecated
1564
1624
  * @static
1565
1625
  * @memberOf _
1566
1626
  * @category Objects
@@ -1572,7 +1632,7 @@
1572
1632
  * // => true
1573
1633
  */
1574
1634
  function isUndefined(value) {
1575
- return value === undefined;
1635
+ return typeof value == 'undefined';
1576
1636
  }
1577
1637
 
1578
1638
  /**
@@ -1991,7 +2051,7 @@
1991
2051
  * @alias detect
1992
2052
  * @category Collections
1993
2053
  * @param {Array|Object|String} collection The collection to iterate over.
1994
- * @param {Function} callback The function called per iteration.
2054
+ * @param {Function} [callback=identity] The function called per iteration.
1995
2055
  * @param {Mixed} [thisArg] The `this` binding of `callback`.
1996
2056
  * @returns {Mixed} Returns the element that passed the callback check,
1997
2057
  * else `undefined`.
@@ -2023,7 +2083,7 @@
2023
2083
  * @alias each
2024
2084
  * @category Collections
2025
2085
  * @param {Array|Object|String} collection The collection to iterate over.
2026
- * @param {Function} callback The function called per iteration.
2086
+ * @param {Function} [callback=identity] The function called per iteration.
2027
2087
  * @param {Mixed} [thisArg] The `this` binding of `callback`.
2028
2088
  * @returns {Array|Object|String} Returns `collection`.
2029
2089
  * @example
@@ -2032,7 +2092,7 @@
2032
2092
  * // => alerts each number and returns '1,2,3'
2033
2093
  *
2034
2094
  * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, alert);
2035
- * // => alerts each number (order is not guaranteed)
2095
+ * // => alerts each number value (order is not guaranteed)
2036
2096
  */
2037
2097
  var forEach = createIterator(forEachIteratorOptions);
2038
2098
 
@@ -2095,7 +2155,7 @@
2095
2155
  * // => [['1', '2', '3'], ['4', '5', '6']]
2096
2156
  */
2097
2157
  function invoke(collection, methodName) {
2098
- var args = slice.call(arguments, 2),
2158
+ var args = slice(arguments, 2),
2099
2159
  isFunc = typeof methodName == 'function',
2100
2160
  result = [];
2101
2161
 
@@ -2264,11 +2324,7 @@
2264
2324
  * // => ['moe', 'larry', 'curly']
2265
2325
  */
2266
2326
  function pluck(collection, property) {
2267
- var result = [];
2268
- forEach(collection, function(value) {
2269
- result.push(value[property]);
2270
- });
2271
- return result;
2327
+ return map(collection, property + '');
2272
2328
  }
2273
2329
 
2274
2330
  /**
@@ -2282,7 +2338,7 @@
2282
2338
  * @alias foldl, inject
2283
2339
  * @category Collections
2284
2340
  * @param {Array|Object|String} collection The collection to iterate over.
2285
- * @param {Function} callback The function called per iteration.
2341
+ * @param {Function} [callback=identity] The function called per iteration.
2286
2342
  * @param {Mixed} [accumulator] Initial value of the accumulator.
2287
2343
  * @param {Mixed} [thisArg] The `this` binding of `callback`.
2288
2344
  * @returns {Mixed} Returns the accumulated value.
@@ -2293,11 +2349,11 @@
2293
2349
  */
2294
2350
  function reduce(collection, callback, accumulator, thisArg) {
2295
2351
  var noaccum = arguments.length < 3;
2296
- callback = createCallback(callback, thisArg);
2352
+ callback || (callback = identity);
2297
2353
  forEach(collection, function(value, index, collection) {
2298
2354
  accumulator = noaccum
2299
2355
  ? (noaccum = false, value)
2300
- : callback(accumulator, value, index, collection)
2356
+ : callback.call(thisArg, accumulator, value, index, collection)
2301
2357
  });
2302
2358
  return accumulator;
2303
2359
  }
@@ -2310,7 +2366,7 @@
2310
2366
  * @alias foldr
2311
2367
  * @category Collections
2312
2368
  * @param {Array|Object|String} collection The collection to iterate over.
2313
- * @param {Function} callback The function called per iteration.
2369
+ * @param {Function} [callback=identity] The function called per iteration.
2314
2370
  * @param {Mixed} [accumulator] Initial value of the accumulator.
2315
2371
  * @param {Mixed} [thisArg] The `this` binding of `callback`.
2316
2372
  * @returns {Mixed} Returns the accumulated value.
@@ -2331,6 +2387,7 @@
2331
2387
  } else if (noCharByIndex && isString(collection)) {
2332
2388
  iteratee = collection.split('');
2333
2389
  }
2390
+ callback || (callback = identity);
2334
2391
  forEach(collection, function(value, index, collection) {
2335
2392
  index = props ? props[--length] : --length;
2336
2393
  accumulator = noaccum
@@ -2501,7 +2558,7 @@
2501
2558
  }
2502
2559
 
2503
2560
  /**
2504
- * Converts the `collection`, to an array.
2561
+ * Converts the `collection` to an array.
2505
2562
  *
2506
2563
  * @static
2507
2564
  * @memberOf _
@@ -2514,10 +2571,11 @@
2514
2571
  * // => [2, 3, 4]
2515
2572
  */
2516
2573
  function toArray(collection) {
2517
- if (collection && typeof collection.length == 'number') {
2518
- return (noArraySliceOnStrings ? isString(collection) : typeof collection == 'string')
2574
+ var length = collection ? collection.length : 0;
2575
+ if (typeof length == 'number') {
2576
+ return noCharByIndex && isString(collection)
2519
2577
  ? collection.split('')
2520
- : slice.call(collection);
2578
+ : slice(collection);
2521
2579
  }
2522
2580
  return values(collection);
2523
2581
  }
@@ -2631,8 +2689,8 @@
2631
2689
  * @param {Number} [n] The number of elements to return.
2632
2690
  * @param- {Object} [guard] Internally used to allow this method to work with
2633
2691
  * others like `_.map` without using their callback `index` argument for `n`.
2634
- * @returns {Mixed} Returns the first element or an array of the first `n`
2635
- * elements of `array`.
2692
+ * @returns {Mixed} Returns the first element, or an array of the first `n`
2693
+ * elements, of `array`.
2636
2694
  * @example
2637
2695
  *
2638
2696
  * _.first([5, 4, 3, 2, 1]);
@@ -2640,7 +2698,10 @@
2640
2698
  */
2641
2699
  function first(array, n, guard) {
2642
2700
  if (array) {
2643
- return (n == null || guard) ? array[0] : slice.call(array, 0, n);
2701
+ var length = array.length;
2702
+ return (n == null || guard)
2703
+ ? array[0]
2704
+ : slice(array, 0, nativeMin(nativeMax(0, n), length));
2644
2705
  }
2645
2706
  }
2646
2707
 
@@ -2733,16 +2794,19 @@
2733
2794
  * @param {Number} [n=1] The number of elements to exclude.
2734
2795
  * @param- {Object} [guard] Internally used to allow this method to work with
2735
2796
  * others like `_.map` without using their callback `index` argument for `n`.
2736
- * @returns {Array} Returns all but the last element or `n` elements of `array`.
2797
+ * @returns {Array} Returns all but the last element, or `n` elements, of `array`.
2737
2798
  * @example
2738
2799
  *
2739
2800
  * _.initial([3, 2, 1]);
2740
2801
  * // => [3, 2]
2741
2802
  */
2742
2803
  function initial(array, n, guard) {
2743
- return array
2744
- ? slice.call(array, 0, -((n == null || guard) ? 1 : n))
2745
- : [];
2804
+ if (!array) {
2805
+ return [];
2806
+ }
2807
+ var length = array.length;
2808
+ n = n == null || guard ? 1 : n || 0;
2809
+ return slice(array, 0, nativeMin(nativeMax(0, length - n), length));
2746
2810
  }
2747
2811
 
2748
2812
  /**
@@ -2791,8 +2855,8 @@
2791
2855
  * @param {Number} [n] The number of elements to return.
2792
2856
  * @param- {Object} [guard] Internally used to allow this method to work with
2793
2857
  * others like `_.map` without using their callback `index` argument for `n`.
2794
- * @returns {Mixed} Returns the last element or an array of the last `n`
2795
- * elements of `array`.
2858
+ * @returns {Mixed} Returns the last element, or an array of the last `n`
2859
+ * elements, of `array`.
2796
2860
  * @example
2797
2861
  *
2798
2862
  * _.last([3, 2, 1]);
@@ -2801,7 +2865,7 @@
2801
2865
  function last(array, n, guard) {
2802
2866
  if (array) {
2803
2867
  var length = array.length;
2804
- return (n == null || guard) ? array[length - 1] : slice.call(array, -n || length);
2868
+ return (n == null || guard) ? array[length - 1] : slice(array, nativeMax(0, length - n));
2805
2869
  }
2806
2870
  }
2807
2871
 
@@ -2909,7 +2973,7 @@
2909
2973
  start = 0;
2910
2974
  }
2911
2975
  // use `Array(length)` so V8 will avoid the slower "dictionary" mode
2912
- // http://www.youtube.com/watch?v=XAqIpGU8ZZk#t=16m27s
2976
+ // http://youtu.be/XAqIpGU8ZZk#t=17m25s
2913
2977
  var index = -1,
2914
2978
  length = nativeMax(0, ceil((end - start) / step)),
2915
2979
  result = Array(length);
@@ -2933,16 +2997,14 @@
2933
2997
  * @param {Number} [n=1] The number of elements to exclude.
2934
2998
  * @param- {Object} [guard] Internally used to allow this method to work with
2935
2999
  * others like `_.map` without using their callback `index` argument for `n`.
2936
- * @returns {Array} Returns all but the first value or `n` values of `array`.
3000
+ * @returns {Array} Returns all but the first element, or `n` elements, of `array`.
2937
3001
  * @example
2938
3002
  *
2939
3003
  * _.rest([3, 2, 1]);
2940
3004
  * // => [2, 1]
2941
3005
  */
2942
3006
  function rest(array, n, guard) {
2943
- return array
2944
- ? slice.call(array, (n == null || guard) ? 1 : n)
2945
- : [];
3007
+ return slice(array, (n == null || guard) ? 1 : nativeMax(0, n));
2946
3008
  }
2947
3009
 
2948
3010
  /**
@@ -3210,7 +3272,7 @@
3210
3272
  // (in V8 `Function#bind` is slower except when partially applied)
3211
3273
  return isBindFast || (nativeBind && arguments.length > 2)
3212
3274
  ? nativeBind.call.apply(nativeBind, arguments)
3213
- : createBound(func, thisArg, slice.call(arguments, 2));
3275
+ : createBound(func, thisArg, slice(arguments, 2));
3214
3276
  }
3215
3277
 
3216
3278
  /**
@@ -3282,7 +3344,7 @@
3282
3344
  * // => 'hi, moe!'
3283
3345
  */
3284
3346
  function bindKey(object, key) {
3285
- return createBound(object, key, slice.call(arguments, 2));
3347
+ return createBound(object, key, slice(arguments, 2));
3286
3348
  }
3287
3349
 
3288
3350
  /**
@@ -3382,7 +3444,7 @@
3382
3444
  * // => 'logged later' (Appears after one second.)
3383
3445
  */
3384
3446
  function delay(func, wait) {
3385
- var args = slice.call(arguments, 2);
3447
+ var args = slice(arguments, 2);
3386
3448
  return setTimeout(function() { func.apply(undefined, args); }, wait);
3387
3449
  }
3388
3450
 
@@ -3402,7 +3464,7 @@
3402
3464
  * // returns from the function before `alert` is called
3403
3465
  */
3404
3466
  function defer(func) {
3405
- var args = slice.call(arguments, 1);
3467
+ var args = slice(arguments, 1);
3406
3468
  return setTimeout(function() { func.apply(undefined, args); }, 1);
3407
3469
  }
3408
3470
 
@@ -3488,7 +3550,7 @@
3488
3550
  * // => 'hi: moe'
3489
3551
  */
3490
3552
  function partial(func) {
3491
- return createBound(func, slice.call(arguments, 1));
3553
+ return createBound(func, slice(arguments, 1));
3492
3554
  }
3493
3555
 
3494
3556
  /**
@@ -3530,6 +3592,7 @@
3530
3592
 
3531
3593
  if (remaining <= 0) {
3532
3594
  clearTimeout(timeoutId);
3595
+ timeoutId = null;
3533
3596
  lastCalled = now;
3534
3597
  result = func.apply(thisArg, args);
3535
3598
  }
@@ -3583,7 +3646,7 @@
3583
3646
  * @example
3584
3647
  *
3585
3648
  * _.escape('Moe, Larry & Curly');
3586
- * // => "Moe, Larry &amp; Curly"
3649
+ * // => 'Moe, Larry &amp; Curly'
3587
3650
  */
3588
3651
  function escape(string) {
3589
3652
  return string == null ? '' : (string + '').replace(reUnescapedHtml, escapeHtmlChar);
@@ -3592,7 +3655,7 @@
3592
3655
  /**
3593
3656
  * This function returns the first argument passed to it.
3594
3657
  *
3595
- * Note: It is used throughout Lo-Dash as a default callback.
3658
+ * Note: This function is used throughout Lo-Dash as a default callback.
3596
3659
  *
3597
3660
  * @static
3598
3661
  * @memberOf _
@@ -3640,11 +3703,7 @@
3640
3703
  push.apply(args, arguments);
3641
3704
 
3642
3705
  var result = func.apply(lodash, args);
3643
- if (this.__chain__) {
3644
- result = new lodash(result);
3645
- result.__chain__ = true;
3646
- }
3647
- return result;
3706
+ return new lodash(result);
3648
3707
  };
3649
3708
  });
3650
3709
  }
@@ -3701,7 +3760,6 @@
3701
3760
  * it will be invoked and its result returned, else the property value is
3702
3761
  * returned. If `object` is falsey, then `null` is returned.
3703
3762
  *
3704
- * @deprecated
3705
3763
  * @static
3706
3764
  * @memberOf _
3707
3765
  * @category Utilities
@@ -3840,13 +3898,21 @@
3840
3898
  source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);
3841
3899
 
3842
3900
  // replace delimiters with snippets
3843
- source +=
3844
- escapeValue ? "' +\n__e(" + escapeValue + ") +\n'" :
3845
- evaluateValue ? "';\n" + evaluateValue + ";\n__p += '" :
3846
- interpolateValue ? "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'" : '';
3847
-
3901
+ if (escapeValue) {
3902
+ source += "' +\n__e(" + escapeValue + ") +\n'";
3903
+ }
3904
+ if (evaluateValue) {
3905
+ source += "';\n" + evaluateValue + ";\n__p += '";
3906
+ }
3907
+ if (interpolateValue) {
3908
+ source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
3909
+ }
3848
3910
  isEvaluating || (isEvaluating = evaluateValue || reComplexDelimiter.test(escapeValue || interpolateValue));
3849
3911
  index = offset + match.length;
3912
+
3913
+ // the JS engine embedded in Adobe products requires returning the `match`
3914
+ // string in order to produce the correct `offset` value
3915
+ return match;
3850
3916
  });
3851
3917
 
3852
3918
  source += "';\n";
@@ -3876,10 +3942,10 @@
3876
3942
  // frame code as the function body
3877
3943
  source = 'function(' + variable + ') {\n' +
3878
3944
  (hasVariable ? '' : variable + ' || (' + variable + ' = {});\n') +
3879
- 'var __t, __p = \'\', __e = _.escape' +
3945
+ "var __t, __p = '', __e = _.escape" +
3880
3946
  (isEvaluating
3881
3947
  ? ', __j = Array.prototype.join;\n' +
3882
- 'function print() { __p += __j.call(arguments, \'\') }\n'
3948
+ "function print() { __p += __j.call(arguments, '') }\n"
3883
3949
  : (hasVariable ? '' : ', __d = ' + variable + '.' + variable + ' || ' + variable) + ';\n'
3884
3950
  ) +
3885
3951
  source +
@@ -3892,7 +3958,7 @@
3892
3958
  : '';
3893
3959
 
3894
3960
  try {
3895
- result = Function('_', 'return ' + source + sourceURL)(lodash);
3961
+ result = createFunction('_', 'return ' + source + sourceURL)(lodash);
3896
3962
  } catch(e) {
3897
3963
  e.source = source;
3898
3964
  throw e;
@@ -3955,29 +4021,30 @@
3955
4021
  * @example
3956
4022
  *
3957
4023
  * _.unescape('Moe, Larry &amp; Curly');
3958
- * // => "Moe, Larry & Curly"
4024
+ * // => 'Moe, Larry & Curly'
3959
4025
  */
3960
4026
  function unescape(string) {
3961
4027
  return string == null ? '' : (string + '').replace(reEscapedHtml, unescapeHtmlChar);
3962
4028
  }
3963
4029
 
3964
4030
  /**
3965
- * Generates a unique id. If `prefix` is passed, the id will be appended to it.
4031
+ * Generates a unique ID. If `prefix` is passed, the ID will be appended to it.
3966
4032
  *
3967
4033
  * @static
3968
4034
  * @memberOf _
3969
4035
  * @category Utilities
3970
- * @param {String} [prefix] The value to prefix the id with.
3971
- * @returns {Number|String} Returns a numeric id if no prefix is passed, else
3972
- * a string id may be returned.
4036
+ * @param {String} [prefix] The value to prefix the ID with.
4037
+ * @returns {String} Returns the unique ID.
3973
4038
  * @example
3974
4039
  *
3975
4040
  * _.uniqueId('contact_');
3976
4041
  * // => 'contact_104'
4042
+ *
4043
+ * _.uniqueId();
4044
+ * // => '105'
3977
4045
  */
3978
4046
  function uniqueId(prefix) {
3979
- var id = idCounter++;
3980
- return prefix ? prefix + id : id;
4047
+ return (prefix == null ? '' : prefix + '') + (++idCounter);
3981
4048
  }
3982
4049
 
3983
4050
  /*--------------------------------------------------------------------------*/
@@ -4001,14 +4068,11 @@
4001
4068
  * var youngest = _.chain(stooges)
4002
4069
  * .sortBy(function(stooge) { return stooge.age; })
4003
4070
  * .map(function(stooge) { return stooge.name + ' is ' + stooge.age; })
4004
- * .first()
4005
- * .value();
4071
+ * .first();
4006
4072
  * // => 'moe is 40'
4007
4073
  */
4008
4074
  function chain(value) {
4009
- value = new lodash(value);
4010
- value.__chain__ = true;
4011
- return value;
4075
+ return new lodash(value);
4012
4076
  }
4013
4077
 
4014
4078
  /**
@@ -4027,7 +4091,7 @@
4027
4091
  * _.chain([1, 2, 3, 200])
4028
4092
  * .filter(function(num) { return num % 2 == 0; })
4029
4093
  * .tap(alert)
4030
- * .map(function(num) { return num * num })
4094
+ * .map(function(num) { return num * num; })
4031
4095
  * .value();
4032
4096
  * // => // [2, 200] (alerted)
4033
4097
  * // => [4, 40000]
@@ -4038,7 +4102,11 @@
4038
4102
  }
4039
4103
 
4040
4104
  /**
4041
- * Enables method chaining on the wrapper object.
4105
+ * This function returns the wrapper object.
4106
+ *
4107
+ * Note: This function is defined to ensure the existing wrapper object is
4108
+ * returned, instead of creating a new wrapper object like the `_.chain`
4109
+ * method does.
4042
4110
  *
4043
4111
  * @name chain
4044
4112
  * @deprecated
@@ -4047,27 +4115,44 @@
4047
4115
  * @returns {Mixed} Returns the wrapper object.
4048
4116
  * @example
4049
4117
  *
4050
- * _([1, 2, 3]).value();
4051
- * // => [1, 2, 3]
4118
+ * var wrapped = _([1, 2, 3]);
4119
+ * wrapped === wrapped.chain();
4120
+ * // => true
4052
4121
  */
4053
4122
  function wrapperChain() {
4054
- this.__chain__ = true;
4055
4123
  return this;
4056
4124
  }
4057
4125
 
4126
+ /**
4127
+ * Produces the `toString` result of the wrapped value.
4128
+ *
4129
+ * @name toString
4130
+ * @memberOf _
4131
+ * @category Chaining
4132
+ * @returns {String} Returns the string result.
4133
+ * @example
4134
+ *
4135
+ * _([1, 2, 3]).toString();
4136
+ * // => '1,2,3'
4137
+ */
4138
+ function wrapperToString() {
4139
+ return String(this.__wrapped__);
4140
+ }
4141
+
4058
4142
  /**
4059
4143
  * Extracts the wrapped value.
4060
4144
  *
4061
- * @name value
4145
+ * @name valueOf
4062
4146
  * @memberOf _
4147
+ * @alias value
4063
4148
  * @category Chaining
4064
4149
  * @returns {Mixed} Returns the wrapped value.
4065
4150
  * @example
4066
4151
  *
4067
- * _([1, 2, 3]).value();
4152
+ * _([1, 2, 3]).valueOf();
4068
4153
  * // => [1, 2, 3]
4069
4154
  */
4070
- function wrapperValue() {
4155
+ function wrapperValueOf() {
4071
4156
  return this.__wrapped__;
4072
4157
  }
4073
4158
 
@@ -4080,7 +4165,7 @@
4080
4165
  * @memberOf _
4081
4166
  * @type String
4082
4167
  */
4083
- lodash.VERSION = '0.10.0';
4168
+ lodash.VERSION = '1.0.0-rc.1';
4084
4169
 
4085
4170
  // assign static methods
4086
4171
  lodash.assign = assign;
@@ -4208,7 +4293,35 @@
4208
4293
  // add `lodash.prototype.chain` after calling `mixin()` to avoid overwriting
4209
4294
  // it with the wrapped `lodash.chain`
4210
4295
  lodash.prototype.chain = wrapperChain;
4211
- lodash.prototype.value = wrapperValue;
4296
+ lodash.prototype.toString = wrapperToString;
4297
+ lodash.prototype.value = wrapperValueOf;
4298
+ lodash.prototype.valueOf = wrapperValueOf;
4299
+
4300
+ // add methods that are capable of returning wrapped and unwrapped values
4301
+ forEach(['first', 'last'], function(methodName) {
4302
+ var func = lodash[methodName];
4303
+ if (func) {
4304
+ lodash.prototype[methodName] = function(n, guard) {
4305
+ var result = func(this.__wrapped__, n, guard);
4306
+ return (n == null || guard)
4307
+ ? result
4308
+ : new lodash(result);
4309
+ };
4310
+ }
4311
+ });
4312
+
4313
+ // add all methods that return unwrapped values
4314
+ forEach(filter(functions(lodash), function(methodName) {
4315
+ return /^(?:bind|contains|every|find|has|is[A-Z].+|reduce.*|some)$/.test(methodName);
4316
+ }), function(methodName) {
4317
+ var func = lodash[methodName];
4318
+
4319
+ lodash.prototype[methodName] = function() {
4320
+ var args = [this.__wrapped__];
4321
+ push.apply(args, arguments);
4322
+ return func.apply(lodash, args);
4323
+ };
4324
+ });
4212
4325
 
4213
4326
  // add all mutator Array functions to the wrapper.
4214
4327
  forEach(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
@@ -4223,11 +4336,7 @@
4223
4336
  if (hasObjectSpliceBug && value.length === 0) {
4224
4337
  delete value[0];
4225
4338
  }
4226
- if (this.__chain__) {
4227
- value = new lodash(value);
4228
- value.__chain__ = true;
4229
- }
4230
- return value;
4339
+ return this;
4231
4340
  };
4232
4341
  });
4233
4342
 
@@ -4239,11 +4348,7 @@
4239
4348
  var value = this.__wrapped__,
4240
4349
  result = func.apply(value, arguments);
4241
4350
 
4242
- if (this.__chain__) {
4243
- result = new lodash(result);
4244
- result.__chain__ = true;
4245
- }
4246
- return result;
4351
+ return new lodash(result);
4247
4352
  };
4248
4353
  });
4249
4354