lodash-rails 0.10.0 → 1.0.0.rc.1

Sign up to get free protection for your applications and to get access to all the features.
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