lodash-rails 0.7.0 → 0.8.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.7.0 (lodash, lodash.min)
21
+ * Lo-Dash 0.8.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.7.0"
3
+ VERSION = "0.8.1"
4
4
  end
5
5
  end
@@ -1,38 +1,13 @@
1
1
  /*!
2
- * Lo-Dash v0.7.0 <http://lodash.com>
3
- * Copyright 2012 John-David Dalton <http://allyoucanleet.com/>
4
- * Based on Underscore.js 1.3.3, copyright 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
5
- * <http://documentcloud.github.com/underscore>
2
+ * Lo-Dash v0.8.1 <http://lodash.com>
3
+ * (c) 2012 John-David Dalton <http://allyoucanleet.com/>
4
+ * Based on Underscore.js 1.4.1 <http://underscorejs.org>
5
+ * (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
6
6
  * Available under MIT license <http://lodash.com/license>
7
7
  */
8
8
  ;(function(window, undefined) {
9
9
  'use strict';
10
10
 
11
- /**
12
- * Used to cache the last `_.templateSettings.evaluate` delimiter to avoid
13
- * unnecessarily assigning `reEvaluateDelimiter` a new generated regexp.
14
- * Assigned in `_.template`.
15
- */
16
- var lastEvaluateDelimiter;
17
-
18
- /**
19
- * Used to cache the last template `options.variable` to avoid unnecessarily
20
- * assigning `reDoubleVariable` a new generated regexp. Assigned in `_.template`.
21
- */
22
- var lastVariable;
23
-
24
- /**
25
- * Used to match potentially incorrect data object references, like `obj.obj`,
26
- * in compiled templates. Assigned in `_.template`.
27
- */
28
- var reDoubleVariable;
29
-
30
- /**
31
- * Used to match "evaluate" delimiters, including internal delimiters,
32
- * in template text. Assigned in `_.template`.
33
- */
34
- var reEvaluateDelimiter;
35
-
36
11
  /** Detect free variable `exports` */
37
12
  var freeExports = typeof exports == 'object' && exports &&
38
13
  (typeof global == 'object' && global && global == global.global && (window = global), exports);
@@ -77,8 +52,8 @@
77
52
  .replace(/valueOf|for [^\]]+/g, '.+?') + '$'
78
53
  );
79
54
 
80
- /** Used to match internally used tokens in template text */
81
- var reToken = /__token(\d+)__/g;
55
+ /** Used to ensure capturing order and avoid matches for undefined delimiters */
56
+ var reNoMatch = /($^)/;
82
57
 
83
58
  /** Used to match HTML characters */
84
59
  var reUnescapedHtml = /[&<>"']/g;
@@ -95,13 +70,6 @@
95
70
  /** Used to make template sourceURLs easier to identify */
96
71
  var templateCounter = 0;
97
72
 
98
- /** Used to replace template delimiters */
99
- var tokenHead = '__token',
100
- tokenFoot = '__';
101
-
102
- /** Used to store tokenized template text snippets */
103
- var tokenized = [];
104
-
105
73
  /** Native method shortcuts */
106
74
  var concat = ArrayProto.concat,
107
75
  hasOwnProperty = ObjectProto.hasOwnProperty,
@@ -113,6 +81,7 @@
113
81
  /* Native method shortcuts for methods with the same name as other `lodash` methods */
114
82
  var nativeBind = reNative.test(nativeBind = slice.bind) && nativeBind,
115
83
  nativeFloor = Math.floor,
84
+ nativeGetPrototypeOf = reNative.test(nativeGetPrototypeOf = Object.getPrototypeOf) && nativeGetPrototypeOf,
116
85
  nativeIsArray = reNative.test(nativeIsArray = Array.isArray) && nativeIsArray,
117
86
  nativeIsFinite = window.isFinite,
118
87
  nativeKeys = reNative.test(nativeKeys = Object.keys) && nativeKeys,
@@ -237,31 +206,6 @@
237
206
  cloneableClasses[numberClass] = cloneableClasses[objectClass] = cloneableClasses[regexpClass] =
238
207
  cloneableClasses[stringClass] = true;
239
208
 
240
- /**
241
- * Used to convert characters to HTML entities:
242
- *
243
- * Though the `>` character is escaped for symmetry, characters like `>` and `/`
244
- * don't require escaping in HTML and have no special meaning unless they're part
245
- * of a tag or an unquoted attribute value.
246
- * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact")
247
- */
248
- var htmlEscapes = {
249
- '&': '&amp;',
250
- '<': '&lt;',
251
- '>': '&gt;',
252
- '"': '&quot;',
253
- "'": '&#x27;'
254
- };
255
-
256
- /** Used to convert HTML entities to characters */
257
- var htmlUnescapes = {
258
- '&amp;': '&',
259
- '&lt;': '<',
260
- '&gt;': '>',
261
- '&quot;': '"',
262
- '&#x27;': "'"
263
- };
264
-
265
209
  /** Used to determine if values are of the language type Object */
266
210
  var objectTypes = {
267
211
  'boolean': false,
@@ -291,26 +235,18 @@
291
235
  *
292
236
  * @name _
293
237
  * @constructor
294
- * @param {Mixed} value The value to wrap in a `LoDash` instance.
295
- * @returns {Object} Returns a `LoDash` instance.
238
+ * @param {Mixed} value The value to wrap in a `lodash` instance.
239
+ * @returns {Object} Returns a `lodash` instance.
296
240
  */
297
241
  function lodash(value) {
298
- // allow invoking `lodash` without the `new` operator
299
- return new LoDash(value);
300
- }
301
-
302
- /**
303
- * Creates a `LoDash` instance that wraps a value to allow chaining.
304
- *
305
- * @private
306
- * @constructor
307
- * @param {Mixed} value The value to wrap.
308
- */
309
- function LoDash(value) {
310
242
  // exit early if already wrapped
311
243
  if (value && value.__wrapped__) {
312
244
  return value;
313
245
  }
246
+ // allow invoking `lodash` without the `new` operator
247
+ if (!(this instanceof lodash)) {
248
+ return new lodash(value);
249
+ }
314
250
  this.__wrapped__ = value;
315
251
  }
316
252
 
@@ -379,15 +315,15 @@
379
315
  'var index, value, iteratee = <%= firstArg %>, ' +
380
316
  // assign the `result` variable an initial value
381
317
  'result<% if (init) { %> = <%= init %><% } %>;\n' +
382
- // add code to exit early or do so if the first argument is falsey
383
- '<%= exit %>;\n' +
384
- // add code after the exit snippet but before the iteration branches
318
+ // exit early if the first argument is falsey
319
+ 'if (!<%= firstArg %>) return result;\n' +
320
+ // add code before the iteration branches
385
321
  '<%= top %>;\n' +
386
322
 
387
323
  // the following branch is for iterating arrays and array-like objects
388
324
  '<% if (arrayBranch) { %>' +
389
325
  'var length = iteratee.length; index = -1;' +
390
- ' <% if (objectBranch) { %>\nif (length > -1 && length === length >>> 0) {<% } %>' +
326
+ ' <% if (objectBranch) { %>\nif (length === +length) {<% } %>' +
391
327
 
392
328
  // add support for accessing string characters by index if needed
393
329
  ' <% if (noCharByIndex) { %>\n' +
@@ -455,8 +391,8 @@
455
391
  ' %>) {' +
456
392
  ' <% } %>\n' +
457
393
  ' value = iteratee[index];\n' +
458
- ' <%= objectBranch.inLoop %>;\n' +
459
- ' <% if (!hasDontEnumBug || useHas) { %>}\n<% } %>' +
394
+ ' <%= objectBranch.inLoop %>;' +
395
+ ' <% if (!hasDontEnumBug || useHas) { %>\n }<% } %>\n' +
460
396
  ' }' +
461
397
  ' <% } %>' +
462
398
 
@@ -488,36 +424,22 @@
488
424
 
489
425
  /**
490
426
  * Reusable iterator options shared by
491
- * `every`, `filter`, `find`, `forEach`, `forIn`, `forOwn`, `groupBy`, `map`,
492
- * `reject`, `some`, and `sortBy`.
427
+ * `countBy`, `every`, `filter`, `find`, `forEach`, `forIn`, `forOwn`, `groupBy`,
428
+ * `map`, `reject`, `some`, and `sortBy`.
493
429
  */
494
430
  var baseIteratorOptions = {
495
431
  'args': 'collection, callback, thisArg',
496
432
  'init': 'collection',
497
- 'top':
498
- 'if (!callback) {\n' +
499
- ' callback = identity\n' +
500
- '}\n' +
501
- 'else if (thisArg) {\n' +
502
- ' callback = iteratorBind(callback, thisArg)\n' +
503
- '}',
433
+ 'top': 'callback = createCallback(callback, thisArg)',
504
434
  'inLoop': 'if (callback(value, index, collection) === false) return result'
505
435
  };
506
436
 
507
437
  /** Reusable iterator options for `countBy`, `groupBy`, and `sortBy` */
508
438
  var countByIteratorOptions = {
509
439
  'init': '{}',
510
- 'top':
511
- 'var prop;\n' +
512
- 'if (typeof callback != \'function\') {\n' +
513
- ' var valueProp = callback;\n' +
514
- ' callback = function(value) { return value[valueProp] }\n' +
515
- '}\n' +
516
- 'else if (thisArg) {\n' +
517
- ' callback = iteratorBind(callback, thisArg)\n' +
518
- '}',
440
+ 'top': 'callback = createCallback(callback, thisArg)',
519
441
  'inLoop':
520
- 'prop = callback(value, index, collection);\n' +
442
+ 'var prop = callback(value, index, collection);\n' +
521
443
  '(hasOwnProperty.call(result, prop) ? result[prop]++ : result[prop] = 1)'
522
444
  };
523
445
 
@@ -548,7 +470,7 @@
548
470
 
549
471
  /** Reusable iterator options for `find`, `forEach`, `forIn`, and `forOwn` */
550
472
  var forEachIteratorOptions = {
551
- 'top': 'if (thisArg) callback = iteratorBind(callback, thisArg)'
473
+ 'top': 'callback = createCallback(callback, thisArg)'
552
474
  };
553
475
 
554
476
  /** Reusable iterator options for `forIn` and `forOwn` */
@@ -560,8 +482,7 @@
560
482
 
561
483
  /** Reusable iterator options for `invoke`, `map`, `pluck`, and `sortBy` */
562
484
  var mapIteratorOptions = {
563
- 'init': '',
564
- 'exit': 'if (!collection) return []',
485
+ 'init': false,
565
486
  'beforeLoop': {
566
487
  'array': 'result = Array(length)',
567
488
  'object': 'result = ' + (isKeysFast ? 'Array(length)' : '[]')
@@ -579,11 +500,8 @@
579
500
  'init': '{}',
580
501
  'top':
581
502
  'var isFunc = typeof callback == \'function\';\n' +
582
- 'if (!isFunc) {\n' +
583
- ' var props = concat.apply(ArrayProto, arguments)\n' +
584
- '} else if (thisArg) {\n' +
585
- ' callback = iteratorBind(callback, thisArg)\n' +
586
- '}',
503
+ 'if (isFunc) callback = createCallback(callback, thisArg);\n' +
504
+ 'else var props = concat.apply(ArrayProto, arguments)',
587
505
  'inLoop':
588
506
  'if (isFunc\n' +
589
507
  ' ? !callback(value, index, object)\n' +
@@ -594,7 +512,7 @@
594
512
  /*--------------------------------------------------------------------------*/
595
513
 
596
514
  /**
597
- * Creates a new function optimized for searching large arrays for a given `value`,
515
+ * Creates a function optimized for searching large arrays for a given `value`,
598
516
  * starting at `fromIndex`, using strict equality for comparisons, i.e. `===`.
599
517
  *
600
518
  * @private
@@ -632,6 +550,114 @@
632
550
  }
633
551
  }
634
552
 
553
+ /**
554
+ * Used by `sortBy` to compare transformed `collection` values, stable sorting
555
+ * them in ascending order.
556
+ *
557
+ * @private
558
+ * @param {Object} a The object to compare to `b`.
559
+ * @param {Object} b The object to compare to `a`.
560
+ * @returns {Number} Returns the sort order indicator of `1` or `-1`.
561
+ */
562
+ function compareAscending(a, b) {
563
+ var ai = a.index,
564
+ bi = b.index;
565
+
566
+ a = a.criteria;
567
+ b = b.criteria;
568
+
569
+ // ensure a stable sort in V8 and other engines
570
+ // http://code.google.com/p/v8/issues/detail?id=90
571
+ if (a !== b) {
572
+ if (a > b || a === undefined) {
573
+ return 1;
574
+ }
575
+ if (a < b || b === undefined) {
576
+ return -1;
577
+ }
578
+ }
579
+ return ai < bi ? -1 : 1;
580
+ }
581
+
582
+ /**
583
+ * Creates a function that, when called, invokes `func` with the `this`
584
+ * binding of `thisArg` and prepends any `partailArgs` to the arguments passed
585
+ * to the bound function.
586
+ *
587
+ * @private
588
+ * @param {Function|String} func The function to bind or the method name.
589
+ * @param {Mixed} [thisArg] The `this` binding of `func`.
590
+ * @param {Array} partialArgs An array of arguments to be partially applied.
591
+ * @returns {Function} Returns the new bound function.
592
+ */
593
+ function createBound(func, thisArg, partialArgs) {
594
+ var isFunc = isFunction(func),
595
+ isPartial = !partialArgs,
596
+ methodName = func;
597
+
598
+ // juggle arguments
599
+ if (isPartial) {
600
+ partialArgs = thisArg;
601
+ }
602
+
603
+ function bound() {
604
+ // `Function#bind` spec
605
+ // http://es5.github.com/#x15.3.4.5
606
+ var args = arguments,
607
+ thisBinding = isPartial ? this : thisArg;
608
+
609
+ if (!isFunc) {
610
+ func = thisArg[methodName];
611
+ }
612
+ if (partialArgs.length) {
613
+ args = args.length
614
+ ? partialArgs.concat(slice.call(args))
615
+ : partialArgs;
616
+ }
617
+ if (this instanceof bound) {
618
+ // get `func` instance if `bound` is invoked in a `new` expression
619
+ noop.prototype = func.prototype;
620
+ thisBinding = new noop;
621
+
622
+ // mimic the constructor's `return` behavior
623
+ // http://es5.github.com/#x13.2.2
624
+ var result = func.apply(thisBinding, args);
625
+ return result && objectTypes[typeof result]
626
+ ? result
627
+ : thisBinding
628
+ }
629
+ return func.apply(thisBinding, args);
630
+ }
631
+ return bound;
632
+ }
633
+
634
+ /**
635
+ * Produces an iteration callback bound to an optional `thisArg`. If `func` is
636
+ * a property name, the callback will return the property value for a given element.
637
+ *
638
+ * @private
639
+ * @param {Function|String} [func=identity|property] The function called per
640
+ * iteration or property name to query.
641
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
642
+ * @returns {Function} Returns a callback function.
643
+ */
644
+ function createCallback(func, thisArg) {
645
+ if (!func) {
646
+ return identity;
647
+ }
648
+ if (typeof func != 'function') {
649
+ return function(object) {
650
+ return object[func];
651
+ };
652
+ }
653
+ if (thisArg !== undefined) {
654
+ return function(value, index, object) {
655
+ return func.call(thisArg, value, index, object);
656
+ };
657
+ }
658
+ return func;
659
+ }
660
+
635
661
  /**
636
662
  * Creates compiled iteration functions. The iteration function will be created
637
663
  * to iterate over only objects if the first argument of `options.args` is
@@ -646,16 +672,11 @@
646
672
  * useStrict - A boolean to specify whether or not to include the ES5
647
673
  * "use strict" directive.
648
674
  *
649
- * args - A string of comma separated arguments the iteration function will
650
- * accept.
675
+ * args - A string of comma separated arguments the iteration function will accept.
651
676
  *
652
677
  * init - A string to specify the initial value of the `result` variable.
653
678
  *
654
- * exit - A string of code to use in place of the default exit-early check
655
- * of `if (!arguments[0]) return result`.
656
- *
657
- * top - A string of code to execute after the exit-early check but before
658
- * the iteration branches.
679
+ * top - A string of code to execute before the iteration branches.
659
680
  *
660
681
  * beforeLoop - A string or object containing an "array" or "object" property
661
682
  * of code to execute before the array or object loops.
@@ -669,33 +690,35 @@
669
690
  * @returns {Function} Returns the compiled function.
670
691
  */
671
692
  function createIterator() {
672
- var object,
673
- prop,
674
- value,
675
- index = -1,
693
+ var index = -1,
676
694
  length = arguments.length;
677
695
 
678
696
  // merge options into a template data object
679
697
  var data = {
680
698
  'bottom': '',
681
- 'exit': '',
682
- 'init': '',
699
+ 'hasDontEnumBug': hasDontEnumBug,
700
+ 'isKeysFast': isKeysFast,
701
+ 'noArgsEnum': noArgsEnum,
702
+ 'noCharByIndex': noCharByIndex,
703
+ 'shadowed': shadowed,
683
704
  'top': '',
684
- 'arrayBranch': { 'beforeLoop': '' },
685
- 'objectBranch': { 'beforeLoop': '' }
705
+ 'useHas': true,
706
+ 'useStrict': isStrictFast,
707
+ 'arrayBranch': {},
708
+ 'objectBranch': {}
686
709
  };
687
710
 
688
711
  while (++index < length) {
689
- object = arguments[index];
690
- for (prop in object) {
691
- value = (value = object[prop]) == null ? '' : value;
712
+ var object = arguments[index];
713
+ for (var prop in object) {
714
+ var value = object[prop];
692
715
  // keep this regexp explicit for the build pre-process
693
716
  if (/beforeLoop|inLoop/.test(prop)) {
694
717
  if (typeof value == 'string') {
695
718
  value = { 'array': value, 'object': value };
696
719
  }
697
- data.arrayBranch[prop] = value.array || '';
698
- data.objectBranch[prop] = value.object || '';
720
+ data.arrayBranch[prop] = value.array;
721
+ data.objectBranch[prop] = value.object;
699
722
  } else {
700
723
  data[prop] = value;
701
724
  }
@@ -704,84 +727,32 @@
704
727
  // set additional template `data` values
705
728
  var args = data.args,
706
729
  firstArg = /^[^,]+/.exec(args)[0],
707
- useStrict = data.useStrict;
730
+ init = data.init;
708
731
 
709
732
  data.firstArg = firstArg;
710
- data.hasDontEnumBug = hasDontEnumBug;
711
- data.isKeysFast = isKeysFast;
712
- data.noArgsEnum = noArgsEnum;
713
- data.shadowed = shadowed;
714
- data.useHas = data.useHas !== false;
715
- data.useStrict = useStrict == null ? isStrictFast : useStrict;
716
-
717
- if (data.noCharByIndex == null) {
718
- data.noCharByIndex = noCharByIndex;
719
- }
720
- if (!data.exit) {
721
- data.exit = 'if (!' + firstArg + ') return result';
722
- }
733
+ data.init = init == null ? firstArg : init;
734
+
723
735
  if (firstArg != 'collection' || !data.arrayBranch.inLoop) {
724
736
  data.arrayBranch = null;
725
737
  }
726
738
  // create the function factory
727
739
  var factory = Function(
728
- 'arrayLikeClasses, ArrayProto, bind, compareAscending, concat, forIn, ' +
729
- 'hasOwnProperty, identity, indexOf, isArguments, isArray, isFunction, ' +
730
- 'isPlainObject, iteratorBind, objectClass, objectTypes, nativeKeys, ' +
731
- 'propertyIsEnumerable, slice, stringClass, toString',
740
+ 'arrayLikeClasses, ArrayProto, bind, compareAscending, concat, createCallback, ' +
741
+ 'forIn, hasOwnProperty, indexOf, isArguments, isArray, isFunction, ' +
742
+ 'isPlainObject, objectClass, objectTypes, nativeKeys, propertyIsEnumerable, ' +
743
+ 'slice, stringClass, toString, undefined',
732
744
  'var callee = function(' + args + ') {\n' + iteratorTemplate(data) + '\n};\n' +
733
745
  'return callee'
734
746
  );
735
747
  // return the compiled function
736
748
  return factory(
737
- arrayLikeClasses, ArrayProto, bind, compareAscending, concat, forIn,
738
- hasOwnProperty, identity, indexOf, isArguments, isArray, isFunction,
739
- isPlainObject, iteratorBind, objectClass, objectTypes, nativeKeys,
740
- propertyIsEnumerable, slice, stringClass, toString
749
+ arrayLikeClasses, ArrayProto, bind, compareAscending, concat, createCallback,
750
+ forIn, hasOwnProperty, indexOf, isArguments, isArray, isFunction,
751
+ isPlainObject, objectClass, objectTypes, nativeKeys, propertyIsEnumerable,
752
+ slice, stringClass, toString
741
753
  );
742
754
  }
743
755
 
744
- /**
745
- * Used by `sortBy` to compare transformed `collection` values, stable sorting
746
- * them in ascending order.
747
- *
748
- * @private
749
- * @param {Object} a The object to compare to `b`.
750
- * @param {Object} b The object to compare to `a`.
751
- * @returns {Number} Returns the sort order indicator of `1` or `-1`.
752
- */
753
- function compareAscending(a, b) {
754
- var ai = a.index,
755
- bi = b.index;
756
-
757
- a = a.criteria;
758
- b = b.criteria;
759
-
760
- // ensure a stable sort in V8 and other engines
761
- // http://code.google.com/p/v8/issues/detail?id=90
762
- if (a !== b) {
763
- if (a > b || a === undefined) {
764
- return 1;
765
- }
766
- if (a < b || b === undefined) {
767
- return -1;
768
- }
769
- }
770
- return ai < bi ? -1 : 1;
771
- }
772
-
773
- /**
774
- * Used by `template` to replace tokens with their corresponding code snippets.
775
- *
776
- * @private
777
- * @param {String} match The matched token.
778
- * @param {String} index The `tokenized` index of the code snippet.
779
- * @returns {String} Returns the code snippet.
780
- */
781
- function detokenize(match, index) {
782
- return tokenized[index];
783
- }
784
-
785
756
  /**
786
757
  * Used by `template` to escape characters for inclusion in compiled
787
758
  * string literals.
@@ -805,21 +776,6 @@
805
776
  return htmlEscapes[match];
806
777
  }
807
778
 
808
- /**
809
- * Creates a new function that, when called, invokes `func` with the `this`
810
- * binding of `thisArg` and the arguments (value, index, object).
811
- *
812
- * @private
813
- * @param {Function} func The function to bind.
814
- * @param {Mixed} [thisArg] The `this` binding of `func`.
815
- * @returns {Function} Returns the new bound function.
816
- */
817
- function iteratorBind(func, thisArg) {
818
- return function(value, index, object) {
819
- return func.call(thisArg, value, index, object);
820
- };
821
- }
822
-
823
779
  /**
824
780
  * A no-operation function.
825
781
  *
@@ -829,62 +785,6 @@
829
785
  // no operation performed
830
786
  }
831
787
 
832
- /**
833
- * Used by `template` to replace "escape" template delimiters with tokens.
834
- *
835
- * @private
836
- * @param {String} match The matched template delimiter.
837
- * @param {String} value The delimiter value.
838
- * @returns {String} Returns a token.
839
- */
840
- function tokenizeEscape(match, value) {
841
- if (match && reComplexDelimiter.test(value)) {
842
- return '<e%-' + value + '%>';
843
- }
844
- var index = tokenized.length;
845
- tokenized[index] = "' +\n__e(" + value + ") +\n'";
846
- return tokenHead + index + tokenFoot;
847
- }
848
-
849
- /**
850
- * Used by `template` to replace "evaluate" template delimiters, or complex
851
- * "escape" and "interpolate" delimiters, with tokens.
852
- *
853
- * @private
854
- * @param {String} match The matched template delimiter.
855
- * @param {String} escapeValue The complex "escape" delimiter value.
856
- * @param {String} interpolateValue The complex "interpolate" delimiter value.
857
- * @param {String} [evaluateValue] The "evaluate" delimiter value.
858
- * @returns {String} Returns a token.
859
- */
860
- function tokenizeEvaluate(match, escapeValue, interpolateValue, evaluateValue) {
861
- if (evaluateValue) {
862
- var index = tokenized.length;
863
- tokenized[index] = "';\n" + evaluateValue + ";\n__p += '";
864
- return tokenHead + index + tokenFoot;
865
- }
866
- return escapeValue
867
- ? tokenizeEscape(null, escapeValue)
868
- : tokenizeInterpolate(null, interpolateValue);
869
- }
870
-
871
- /**
872
- * Used by `template` to replace "interpolate" template delimiters with tokens.
873
- *
874
- * @private
875
- * @param {String} match The matched template delimiter.
876
- * @param {String} value The delimiter value.
877
- * @returns {String} Returns a token.
878
- */
879
- function tokenizeInterpolate(match, value) {
880
- if (match && reComplexDelimiter.test(value)) {
881
- return '<e%=' + value + '%>';
882
- }
883
- var index = tokenized.length;
884
- tokenized[index] = "' +\n((__t = (" + value + ")) == null ? '' : __t) +\n'";
885
- return tokenHead + index + tokenFoot;
886
- }
887
-
888
788
  /**
889
789
  * Used by `unescape` to convert HTML entities to characters.
890
790
  *
@@ -898,6 +798,25 @@
898
798
 
899
799
  /*--------------------------------------------------------------------------*/
900
800
 
801
+ /**
802
+ * Creates an object composed of the inverted keys and values of the given `object`.
803
+ *
804
+ * @static
805
+ * @memberOf _
806
+ * @category Objects
807
+ * @param {Object} object The object to invert.
808
+ * @returns {Object} Returns the created inverted object.
809
+ * @example
810
+ *
811
+ * _.invert({ 'first': 'Moe', 'second': 'Larry', 'third': 'Curly' });
812
+ * // => { 'Moe': 'first', 'Larry': 'second', 'Curly': 'third' } (order is not guaranteed)
813
+ */
814
+ var invert = createIterator({
815
+ 'args': 'object',
816
+ 'init': '{}',
817
+ 'inLoop': 'result[value] = index'
818
+ });
819
+
901
820
  /**
902
821
  * Checks if `value` is an `arguments` object.
903
822
  *
@@ -920,7 +839,7 @@
920
839
  // fallback for browsers that can't detect `arguments` objects by [[Class]]
921
840
  if (noArgsClass) {
922
841
  isArguments = function(value) {
923
- return !!(value && hasOwnProperty.call(value, 'callee'));
842
+ return value ? hasOwnProperty.call(value, 'callee') : false;
924
843
  };
925
844
  }
926
845
 
@@ -954,7 +873,7 @@
954
873
  * @returns {Boolean} Returns `true` if the `value` is a function, else `false`.
955
874
  * @example
956
875
  *
957
- * _.isFunction(''.concat);
876
+ * _.isFunction(_);
958
877
  * // => true
959
878
  */
960
879
  function isFunction(value) {
@@ -967,6 +886,42 @@
967
886
  };
968
887
  }
969
888
 
889
+ /**
890
+ * Checks if a given `value` is an object created by the `Object` constructor.
891
+ *
892
+ * @static
893
+ * @memberOf _
894
+ * @category Objects
895
+ * @param {Mixed} value The value to check.
896
+ * @returns {Boolean} Returns `true` if `value` is a plain object, else `false`.
897
+ * @example
898
+ *
899
+ * function Stooge(name, age) {
900
+ * this.name = name;
901
+ * this.age = age;
902
+ * }
903
+ *
904
+ * _.isPlainObject(new Stooge('moe', 40));
905
+ * // false
906
+ *
907
+ * _.isPlainObject([1, 2, 3]);
908
+ * // false
909
+ *
910
+ * _.isPlainObject({ 'name': 'moe', 'age': 40 });
911
+ * // => true
912
+ */
913
+ var isPlainObject = !nativeGetPrototypeOf ? isPlainFallback : function(value) {
914
+ if (!(value && typeof value == 'object')) {
915
+ return false;
916
+ }
917
+ var valueOf = value.valueOf,
918
+ objProto = typeof valueOf == 'function' && (objProto = nativeGetPrototypeOf(valueOf)) && nativeGetPrototypeOf(objProto);
919
+
920
+ return objProto
921
+ ? value == objProto || (nativeGetPrototypeOf(value) == objProto && !isArguments(value))
922
+ : isPlainFallback(value);
923
+ };
924
+
970
925
  /**
971
926
  * A fallback implementation of `isPlainObject` that checks if a given `value`
972
927
  * is an object created by the `Object` constructor, assuming objects created
@@ -975,14 +930,12 @@
975
930
  *
976
931
  * @private
977
932
  * @param {Mixed} value The value to check.
978
- * @param {Boolean} [skipArgsCheck=false] Internally used to skip checks for
979
- * `arguments` objects.
980
933
  * @returns {Boolean} Returns `true` if `value` is a plain object, else `false`.
981
934
  */
982
- function isPlainFallback(value, skipArgsCheck) {
935
+ function isPlainFallback(value) {
983
936
  // avoid non-objects and false positives for `arguments` objects
984
937
  var result = false;
985
- if (!(value && typeof value == 'object') || (!skipArgsCheck && isArguments(value))) {
938
+ if (!(value && typeof value == 'object') || isArguments(value)) {
986
939
  return result;
987
940
  }
988
941
  // IE < 9 presents DOM nodes as `Object` objects except they have `toString`
@@ -1012,27 +965,6 @@
1012
965
  return result;
1013
966
  }
1014
967
 
1015
- /**
1016
- * Checks if a given `value` is an object created by the `Object` constructor.
1017
- *
1018
- * @private
1019
- * @param {Mixed} value The value to check.
1020
- * @param {Boolean} [skipArgsCheck=false] Internally used to skip checks for
1021
- * `arguments` objects.
1022
- * @returns {Boolean} Returns `true` if `value` is a plain object, else `false`.
1023
- */
1024
- var isPlainObject = objectTypes.__proto__ != ObjectProto ? isPlainFallback : function(value, skipArgsCheck) {
1025
- if (!value) {
1026
- return false;
1027
- }
1028
- var valueOf = value.valueOf,
1029
- objProto = typeof valueOf == 'function' && (objProto = valueOf.__proto__) && objProto.__proto__;
1030
-
1031
- return objProto
1032
- ? value == objProto || (value.__proto__ == objProto && (skipArgsCheck || !isArguments(value)))
1033
- : isPlainFallback(value);
1034
- };
1035
-
1036
968
  /**
1037
969
  * A shim implementation of `Object.keys` that produces an array of the given
1038
970
  * object's own enumerable property names.
@@ -1047,25 +979,43 @@
1047
979
  'inLoop': 'result.push(index)'
1048
980
  });
1049
981
 
982
+ /**
983
+ * Used to convert characters to HTML entities:
984
+ *
985
+ * Though the `>` character is escaped for symmetry, characters like `>` and `/`
986
+ * don't require escaping in HTML and have no special meaning unless they're part
987
+ * of a tag or an unquoted attribute value.
988
+ * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact")
989
+ */
990
+ var htmlEscapes = {
991
+ '&': '&amp;',
992
+ '<': '&lt;',
993
+ '>': '&gt;',
994
+ '"': '&quot;',
995
+ "'": '&#x27;'
996
+ };
997
+
998
+ /** Used to convert HTML entities to characters */
999
+ var htmlUnescapes = invert(htmlEscapes);
1000
+
1050
1001
  /*--------------------------------------------------------------------------*/
1051
1002
 
1052
1003
  /**
1053
1004
  * Creates a clone of `value`. If `deep` is `true`, all nested objects will
1054
- * also be cloned otherwise they will be assigned by reference. If a value has
1055
- * a `clone` method it will be used to perform the clone. Functions, DOM nodes,
1056
- * `arguments` objects, and objects created by constructors other than `Object`
1057
- * are **not** cloned unless they have a custom `clone` method.
1005
+ * also be cloned otherwise they will be assigned by reference. Functions, DOM
1006
+ * nodes, `arguments` objects, and objects created by constructors other than
1007
+ * `Object` are **not** cloned.
1058
1008
  *
1059
1009
  * @static
1060
1010
  * @memberOf _
1061
1011
  * @category Objects
1062
1012
  * @param {Mixed} value The value to clone.
1063
1013
  * @param {Boolean} deep A flag to indicate a deep clone.
1064
- * @param {Object} [guard] Internally used to allow this method to work with
1014
+ * @param- {Object} [guard] Internally used to allow this method to work with
1065
1015
  * others like `_.map` without using their callback `index` argument for `deep`.
1066
- * @param {Object} [data={}] Internally used to track traversed objects to avoid
1067
- * circular references and indicate whether to perform a more thorough clone
1068
- * of non-object values.
1016
+ * @param- {Array} [stackA=[]] Internally used to track traversed source objects.
1017
+ * @param- {Array} [stackB=[]] Internally used to associate clones with their
1018
+ * source counterparts.
1069
1019
  * @returns {Mixed} Returns the cloned `value`.
1070
1020
  * @example
1071
1021
  *
@@ -1086,28 +1036,15 @@
1086
1036
  * shallow[0] === stooges[0];
1087
1037
  * // => false
1088
1038
  */
1089
- function clone(value, deep, guard, data) {
1039
+ function clone(value, deep, guard, stackA, stackB) {
1090
1040
  if (value == null) {
1091
1041
  return value;
1092
1042
  }
1093
1043
  if (guard) {
1094
1044
  deep = false;
1095
1045
  }
1096
- // init internal data
1097
- data || (data = { 'thorough': null });
1098
-
1099
- // avoid slower checks on primitives
1100
- if (data.thorough == null) {
1101
- // primitives passed from iframes use the primary document's native prototypes
1102
- data.thorough = !!(BoolProto.clone || NumberProto.clone || StringProto.clone);
1103
- }
1104
- // use custom `clone` method if available
1105
- var isObj = objectTypes[typeof value];
1106
- if ((isObj || data.thorough) && value.clone && isFunction(value.clone)) {
1107
- data.thorough = null;
1108
- return value.clone(deep);
1109
- }
1110
1046
  // inspect [[Class]]
1047
+ var isObj = objectTypes[typeof value];
1111
1048
  if (isObj) {
1112
1049
  // don't clone `arguments` objects, functions, or non-object Objects
1113
1050
  var className = toString.call(value);
@@ -1115,7 +1052,7 @@
1115
1052
  return value;
1116
1053
  }
1117
1054
  var isArr = className == arrayClass;
1118
- isObj = isArr || (className == objectClass ? isPlainObject(value, true) : isObj);
1055
+ isObj = isArr || (className == objectClass ? isPlainObject(value) : isObj);
1119
1056
  }
1120
1057
  // shallow clone
1121
1058
  if (!isObj || !deep) {
@@ -1141,33 +1078,34 @@
1141
1078
  return ctor(value.source, reFlags.exec(value));
1142
1079
  }
1143
1080
 
1144
- var clones = data.clones || (data.clones = []),
1145
- sources = data.sources || (data.sources = []),
1146
- length = clones.length;
1147
-
1148
1081
  // check for circular references and return corresponding clone
1082
+ stackA || (stackA = []);
1083
+ stackB || (stackB = []);
1084
+
1085
+ var length = stackA.length;
1149
1086
  while (length--) {
1150
- if (sources[length] == value) {
1151
- return clones[length];
1087
+ if (stackA[length] == value) {
1088
+ return stackB[length];
1152
1089
  }
1153
1090
  }
1154
1091
 
1155
1092
  // init cloned object
1156
1093
  var result = isArr ? ctor(length = value.length) : {};
1157
1094
 
1158
- // add current clone and original source value to the stack of traversed objects
1159
- clones.push(result);
1160
- sources.push(value);
1095
+ // add the source value to the stack of traversed objects
1096
+ // and associate it with its clone
1097
+ stackA.push(value);
1098
+ stackB.push(result);
1161
1099
 
1162
1100
  // recursively populate clone (susceptible to call stack limits)
1163
1101
  if (isArr) {
1164
1102
  var index = -1;
1165
1103
  while (++index < length) {
1166
- result[index] = clone(value[index], deep, null, data);
1104
+ result[index] = clone(value[index], deep, null, stackA, stackB);
1167
1105
  }
1168
1106
  } else {
1169
1107
  forOwn(value, function(objValue, key) {
1170
- result[key] = clone(objValue, deep, null, data);
1108
+ result[key] = clone(objValue, deep, null, stackA, stackB);
1171
1109
  });
1172
1110
  }
1173
1111
  return result;
@@ -1216,7 +1154,7 @@
1216
1154
  /**
1217
1155
  * Iterates over `object`'s own and inherited enumerable properties, executing
1218
1156
  * the `callback` for each property. The `callback` is bound to `thisArg` and
1219
- * invoked with 3 arguments; (value, key, object). Callbacks may exit iteration
1157
+ * invoked with three arguments; (value, key, object). Callbacks may exit iteration
1220
1158
  * early by explicitly returning `false`.
1221
1159
  *
1222
1160
  * @static
@@ -1224,7 +1162,7 @@
1224
1162
  * @category Objects
1225
1163
  * @param {Object} object The object to iterate over.
1226
1164
  * @param {Function} callback The function called per iteration.
1227
- * @param {Mixed} [thisArg] The `this` binding for the callback.
1165
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
1228
1166
  * @returns {Object} Returns `object`.
1229
1167
  * @example
1230
1168
  *
@@ -1247,16 +1185,16 @@
1247
1185
 
1248
1186
  /**
1249
1187
  * Iterates over `object`'s own enumerable properties, executing the `callback`
1250
- * for each property. The `callback` is bound to `thisArg` and invoked with 3
1251
- * arguments; (value, key, object). Callbacks may exit iteration early by
1252
- * explicitly returning `false`.
1188
+ * for each property. The `callback` is bound to `thisArg` and invoked with three
1189
+ * arguments; (value, key, object). Callbacks may exit iteration early by explicitly
1190
+ * returning `false`.
1253
1191
  *
1254
1192
  * @static
1255
1193
  * @memberOf _
1256
1194
  * @category Objects
1257
1195
  * @param {Object} object The object to iterate over.
1258
1196
  * @param {Function} callback The function called per iteration.
1259
- * @param {Mixed} [thisArg] The `this` binding for the callback.
1197
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
1260
1198
  * @returns {Object} Returns `object`.
1261
1199
  * @example
1262
1200
  *
@@ -1298,35 +1236,16 @@
1298
1236
  * @memberOf _
1299
1237
  * @category Objects
1300
1238
  * @param {Object} object The object to check.
1301
- * @param {String} property The property to check for.
1302
- * @returns {Boolean} Returns `true` if key is a direct property, else `false`.
1303
- * @example
1304
- *
1305
- * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
1306
- * // => true
1307
- */
1308
- function has(object, property) {
1309
- return object ? hasOwnProperty.call(object, property) : false;
1310
- }
1311
-
1312
- /**
1313
- * Creates an object composed of the inverted keys and values of the given `object`.
1314
- *
1315
- * @static
1316
- * @memberOf _
1317
- * @category Objects
1318
- * @param {Object} object The object to invert.
1319
- * @returns {Object} Returns the created inverted object.
1239
+ * @param {String} property The property to check for.
1240
+ * @returns {Boolean} Returns `true` if key is a direct property, else `false`.
1320
1241
  * @example
1321
1242
  *
1322
- * _.invert({ 'first': 'Moe', 'second': 'Larry', 'third': 'Curly' });
1323
- * // => { 'Moe': 'first', 'Larry': 'second', 'Curly': 'third' } (order is not guaranteed)
1243
+ * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
1244
+ * // => true
1324
1245
  */
1325
- var invert = createIterator({
1326
- 'args': 'object',
1327
- 'init': '{}',
1328
- 'inLoop': 'result[value] = index'
1329
- });
1246
+ function has(object, property) {
1247
+ return object ? hasOwnProperty.call(object, property) : false;
1248
+ }
1330
1249
 
1331
1250
  /**
1332
1251
  * Checks if `value` is a boolean (`true` or `false`) value.
@@ -1408,7 +1327,7 @@
1408
1327
  ' length = value.length;\n' +
1409
1328
  'if (arrayLikeClasses[className]' +
1410
1329
  (noArgsClass ? ' || isArguments(value)' : '') + ' ||\n' +
1411
- ' (className == objectClass && length > -1 && length === length >>> 0 &&\n' +
1330
+ ' (className == objectClass && length === +length &&\n' +
1412
1331
  ' isFunction(value.splice))' +
1413
1332
  ') return !length',
1414
1333
  'inLoop': {
@@ -1418,17 +1337,15 @@
1418
1337
 
1419
1338
  /**
1420
1339
  * Performs a deep comparison between two values to determine if they are
1421
- * equivalent to each other. If a value has an `isEqual` method it will be
1422
- * used to perform the comparison.
1340
+ * equivalent to each other.
1423
1341
  *
1424
1342
  * @static
1425
1343
  * @memberOf _
1426
1344
  * @category Objects
1427
1345
  * @param {Mixed} a The value to compare.
1428
1346
  * @param {Mixed} b The other value to compare.
1429
- * @param {Object} [data={}] Internally used track traversed objects to avoid
1430
- * circular references and indicate whether to perform a more thorough comparison
1431
- * of non-object values.
1347
+ * @param- {Object} [stackA=[]] Internally used track traversed `a` objects.
1348
+ * @param- {Object} [stackB=[]] Internally used track traversed `b` objects.
1432
1349
  * @returns {Boolean} Returns `true` if the values are equvalent, else `false`.
1433
1350
  * @example
1434
1351
  *
@@ -1441,39 +1358,21 @@
1441
1358
  * _.isEqual(moe, clone);
1442
1359
  * // => true
1443
1360
  */
1444
- function isEqual(a, b, data) {
1361
+ function isEqual(a, b, stackA, stackB) {
1445
1362
  // a strict comparison is necessary because `null == undefined`
1446
1363
  if (a == null || b == null) {
1447
1364
  return a === b;
1448
1365
  }
1449
- // init internal data
1450
- data || (data = { 'thorough': null });
1451
-
1452
- // avoid slower checks on non-objects
1453
- if (data.thorough == null) {
1454
- // primitives passed from iframes use the primary document's native prototypes
1455
- data.thorough = !!(BoolProto.isEqual || NumberProto.isEqual || StringProto.isEqual);
1456
- }
1457
- if (objectTypes[typeof a] || objectTypes[typeof b] || data.thorough) {
1458
- // unwrap any LoDash wrapped values
1459
- a = a.__wrapped__ || a;
1460
- b = b.__wrapped__ || b;
1461
-
1462
- // use custom `isEqual` method if available
1463
- if (a.isEqual && isFunction(a.isEqual)) {
1464
- data.thorough = null;
1465
- return a.isEqual(b);
1466
- }
1467
- if (b.isEqual && isFunction(b.isEqual)) {
1468
- data.thorough = null;
1469
- return b.isEqual(a);
1470
- }
1471
- }
1472
1366
  // exit early for identical values
1473
1367
  if (a === b) {
1474
1368
  // treat `+0` vs. `-0` as not equal
1475
1369
  return a !== 0 || (1 / a == 1 / b);
1476
1370
  }
1371
+ // unwrap any `lodash` wrapped values
1372
+ if (objectTypes[typeof a] || objectTypes[typeof b]) {
1373
+ a = a.__wrapped__ || a;
1374
+ b = b.__wrapped__ || b;
1375
+ }
1477
1376
  // compare [[Class]] names
1478
1377
  var className = toString.call(a);
1479
1378
  if (className != toString.call(b)) {
@@ -1514,10 +1413,10 @@
1514
1413
  // assume cyclic structures are equal
1515
1414
  // the algorithm for detecting cyclic structures is adapted from ES 5.1
1516
1415
  // section 15.12.3, abstract operation `JO` (http://es5.github.com/#x15.12.3)
1517
- var stackA = data.stackA || (data.stackA = []),
1518
- stackB = data.stackB || (data.stackB = []),
1519
- length = stackA.length;
1416
+ stackA || (stackA = []);
1417
+ stackB || (stackB = []);
1520
1418
 
1419
+ var length = stackA.length;
1521
1420
  while (length--) {
1522
1421
  if (stackA[length] == a) {
1523
1422
  return stackB[length] == b;
@@ -1541,7 +1440,7 @@
1541
1440
  if (result) {
1542
1441
  // deep compare the contents, ignoring non-numeric properties
1543
1442
  while (size--) {
1544
- if (!(result = isEqual(a[size], b[size], data))) {
1443
+ if (!(result = isEqual(a[size], b[size], stackA, stackB))) {
1545
1444
  break;
1546
1445
  }
1547
1446
  }
@@ -1565,7 +1464,7 @@
1565
1464
  // count the number of properties.
1566
1465
  size++;
1567
1466
  // deep compare each property value.
1568
- if (!(hasOwnProperty.call(b, prop) && isEqual(a[prop], b[prop], data))) {
1467
+ if (!(hasOwnProperty.call(b, prop) && isEqual(a[prop], b[prop], stackA, stackB))) {
1569
1468
  return false;
1570
1469
  }
1571
1470
  }
@@ -1585,7 +1484,7 @@
1585
1484
  while (++index < 7) {
1586
1485
  prop = shadowed[index];
1587
1486
  if (hasOwnProperty.call(a, prop) &&
1588
- !(hasOwnProperty.call(b, prop) && isEqual(a[prop], b[prop], data))) {
1487
+ !(hasOwnProperty.call(b, prop) && isEqual(a[prop], b[prop], stackA, stackB))) {
1589
1488
  return false;
1590
1489
  }
1591
1490
  }
@@ -1634,6 +1533,9 @@
1634
1533
  * _.isObject({});
1635
1534
  * // => true
1636
1535
  *
1536
+ * _.isObject([1, 2, 3]);
1537
+ * // => true
1538
+ *
1637
1539
  * _.isObject(1);
1638
1540
  * // => false
1639
1541
  */
@@ -1708,7 +1610,7 @@
1708
1610
  * @returns {Boolean} Returns `true` if the `value` is a number, else `false`.
1709
1611
  * @example
1710
1612
  *
1711
- * _.isNumber(8.4 * 5;
1613
+ * _.isNumber(8.4 * 5);
1712
1614
  * // => true
1713
1615
  */
1714
1616
  function isNumber(value) {
@@ -1789,7 +1691,7 @@
1789
1691
  }
1790
1692
  return object && objectTypes[type]
1791
1693
  ? nativeKeys(object)
1792
- : [];
1694
+ : [];
1793
1695
  };
1794
1696
 
1795
1697
  /**
@@ -1802,10 +1704,11 @@
1802
1704
  * @category Objects
1803
1705
  * @param {Object} object The destination object.
1804
1706
  * @param {Object} [source1, source2, ...] The source objects.
1805
- * @param {Object} [indicator] Internally used to indicate that the `stack`
1707
+ * @param- {Object} [indicator] Internally used to indicate that the `stack`
1806
1708
  * argument is an array of traversed objects instead of another source object.
1807
- * @param {Object} [data={}] Internally used to track traversed objects to avoid
1808
- * circular references.
1709
+ * @param- {Array} [stackA=[]] Internally used to track traversed source objects.
1710
+ * @param- {Array} [stackB=[]] Internally used to associate clones with their
1711
+ * source counterparts.
1809
1712
  * @returns {Object} Returns the destination object.
1810
1713
  * @example
1811
1714
  *
@@ -1825,25 +1728,29 @@
1825
1728
  var merge = createIterator(extendIteratorOptions, {
1826
1729
  'args': 'object, source, indicator',
1827
1730
  'top':
1828
- 'var isArr, source, recursive = indicator == isPlainObject,\n' +
1829
- ' data = recursive ? arguments[3] : { values: [], sources: [] };\n' +
1830
- 'for (var argsIndex = 1, argsLength = recursive ? 2 : arguments.length; argsIndex < argsLength; argsIndex++) {\n' +
1831
- ' if (iteratee = arguments[argsIndex]) {',
1731
+ 'var isArr, args = arguments, argsIndex = 0;\n' +
1732
+ 'if (indicator == compareAscending) {\n' +
1733
+ ' var argsLength = 2, stackA = args[3], stackB = args[4]\n' +
1734
+ '} else {\n' +
1735
+ ' var argsLength = args.length, stackA = [], stackB = []\n' +
1736
+ '}\n' +
1737
+ 'while (++argsIndex < argsLength) {\n' +
1738
+ ' if (iteratee = args[argsIndex]) {',
1832
1739
  'inLoop':
1833
1740
  'if ((source = value) && ((isArr = isArray(source)) || isPlainObject(source))) {\n' +
1834
- ' var found = false, values = data.values, sources = data.sources, stackLength = sources.length;\n' +
1741
+ ' var found = false, stackLength = stackA.length;\n' +
1835
1742
  ' while (stackLength--) {\n' +
1836
- ' if (found = sources[stackLength] == source) break\n' +
1743
+ ' if (found = stackA[stackLength] == source) break\n' +
1837
1744
  ' }\n' +
1838
1745
  ' if (found) {\n' +
1839
- ' result[index] = values[stackLength]\n' +
1746
+ ' result[index] = stackB[stackLength]\n' +
1840
1747
  ' } else {\n' +
1841
- ' values.push(value = (value = result[index]) && isArr\n' +
1748
+ ' stackA.push(source);\n' +
1749
+ ' stackB.push(value = (value = result[index]) && isArr\n' +
1842
1750
  ' ? (isArray(value) ? value : [])\n' +
1843
1751
  ' : (isPlainObject(value) ? value : {})\n' +
1844
1752
  ' );\n' +
1845
- ' sources.push(source);\n' +
1846
- ' result[index] = callee(value, source, isPlainObject, data)\n' +
1753
+ ' result[index] = callee(value, source, compareAscending, stackA, stackB)\n' +
1847
1754
  ' }\n' +
1848
1755
  '} else if (source != null) {\n' +
1849
1756
  ' result[index] = source\n' +
@@ -1855,7 +1762,7 @@
1855
1762
  * Property names may be specified as individual arguments or as arrays of
1856
1763
  * property names. If `callback` is passed, it will be executed for each property
1857
1764
  * in the `object`, omitting the properties `callback` returns truthy for. The
1858
- * `callback` is bound to `thisArg` and invoked with 3 arguments; (value, key, object).
1765
+ * `callback` is bound to `thisArg` and invoked with three arguments; (value, key, object).
1859
1766
  *
1860
1767
  * @static
1861
1768
  * @memberOf _
@@ -1863,7 +1770,7 @@
1863
1770
  * @param {Object} object The source object.
1864
1771
  * @param {Function|String} callback|[prop1, prop2, ...] The properties to omit
1865
1772
  * or the function called per iteration.
1866
- * @param {Mixed} [thisArg] The `this` binding for the callback.
1773
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
1867
1774
  * @returns {Object} Returns an object without the omitted properties.
1868
1775
  * @example
1869
1776
  *
@@ -1902,7 +1809,7 @@
1902
1809
  * Property names may be specified as individual arguments or as arrays of
1903
1810
  * property names. If `callback` is passed, it will be executed for each property
1904
1811
  * in the `object`, picking the properties `callback` returns truthy for. The
1905
- * `callback` is bound to `thisArg` and invoked with 3 arguments; (value, key, object).
1812
+ * `callback` is bound to `thisArg` and invoked with three arguments; (value, key, object).
1906
1813
  *
1907
1814
  * @static
1908
1815
  * @memberOf _
@@ -1910,7 +1817,7 @@
1910
1817
  * @param {Object} object The source object.
1911
1818
  * @param {Function|String} callback|[prop1, prop2, ...] The properties to pick
1912
1819
  * or the function called per iteration.
1913
- * @param {Mixed} [thisArg] The `this` binding for the callback.
1820
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
1914
1821
  * @returns {Object} Returns an object composed of the picked properties.
1915
1822
  * @example
1916
1823
  *
@@ -1933,7 +1840,7 @@
1933
1840
  ' if (prop in object) result[prop] = object[prop]\n' +
1934
1841
  ' }\n' +
1935
1842
  '} else {\n' +
1936
- ' if (thisArg) callback = iteratorBind(callback, thisArg)',
1843
+ ' callback = createCallback(callback, thisArg)',
1937
1844
  'inLoop':
1938
1845
  'if (callback(value, index, object)) result[index] = value',
1939
1846
  'bottom': '}'
@@ -1996,7 +1903,7 @@
1996
1903
  * Creates an object composed of keys returned from running each element of
1997
1904
  * `collection` through a `callback`. The corresponding value of each key is
1998
1905
  * the number of times the key was returned by `callback`. The `callback` is
1999
- * bound to `thisArg` and invoked with 3 arguments; (value, index|key, collection).
1906
+ * bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
2000
1907
  * The `callback` argument may also be the name of a property to count by (e.g. 'length').
2001
1908
  *
2002
1909
  * @static
@@ -2005,7 +1912,7 @@
2005
1912
  * @param {Array|Object|String} collection The collection to iterate over.
2006
1913
  * @param {Function|String} callback|property The function called per iteration
2007
1914
  * or property name to count by.
2008
- * @param {Mixed} [thisArg] The `this` binding for the callback.
1915
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
2009
1916
  * @returns {Object} Returns the composed aggregate object.
2010
1917
  * @example
2011
1918
  *
@@ -2022,7 +1929,7 @@
2022
1929
 
2023
1930
  /**
2024
1931
  * Checks if the `callback` returns a truthy value for **all** elements of a
2025
- * `collection`. The `callback` is bound to `thisArg` and invoked with 3
1932
+ * `collection`. The `callback` is bound to `thisArg` and invoked with three
2026
1933
  * arguments; (value, index|key, collection).
2027
1934
  *
2028
1935
  * @static
@@ -2031,8 +1938,9 @@
2031
1938
  * @category Collections
2032
1939
  * @param {Array|Object|String} collection The collection to iterate over.
2033
1940
  * @param {Function} [callback=identity] The function called per iteration.
2034
- * @param {Mixed} [thisArg] The `this` binding for the callback.
2035
- * @returns {Boolean} Returns `true` if all elements pass the callback check, else `false`.
1941
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
1942
+ * @returns {Boolean} Returns `true` if all elements pass the callback check,
1943
+ * else `false`.
2036
1944
  * @example
2037
1945
  *
2038
1946
  * _.every([true, 1, null, 'yes'], Boolean);
@@ -2043,7 +1951,7 @@
2043
1951
  /**
2044
1952
  * Examines each element in a `collection`, returning an array of all elements
2045
1953
  * the `callback` returns truthy for. The `callback` is bound to `thisArg` and
2046
- * invoked with 3 arguments; (value, index|key, collection).
1954
+ * invoked with three arguments; (value, index|key, collection).
2047
1955
  *
2048
1956
  * @static
2049
1957
  * @memberOf _
@@ -2051,8 +1959,8 @@
2051
1959
  * @category Collections
2052
1960
  * @param {Array|Object|String} collection The collection to iterate over.
2053
1961
  * @param {Function} [callback=identity] The function called per iteration.
2054
- * @param {Mixed} [thisArg] The `this` binding for the callback.
2055
- * @returns {Array} Returns a new array of elements that passed callback check.
1962
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
1963
+ * @returns {Array} Returns a new array of elements that passed the callback check.
2056
1964
  * @example
2057
1965
  *
2058
1966
  * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
@@ -2064,7 +1972,7 @@
2064
1972
  * Examines each element in a `collection`, returning the first one the `callback`
2065
1973
  * returns truthy for. The function returns as soon as it finds an acceptable
2066
1974
  * element, and does not iterate over the entire `collection`. The `callback` is
2067
- * bound to `thisArg` and invoked with 3 arguments; (value, index|key, collection).
1975
+ * bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
2068
1976
  *
2069
1977
  * @static
2070
1978
  * @memberOf _
@@ -2072,23 +1980,24 @@
2072
1980
  * @category Collections
2073
1981
  * @param {Array|Object|String} collection The collection to iterate over.
2074
1982
  * @param {Function} callback The function called per iteration.
2075
- * @param {Mixed} [thisArg] The `this` binding for the callback.
2076
- * @returns {Mixed} Returns the element that passed the callback check, else `undefined`.
1983
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
1984
+ * @returns {Mixed} Returns the element that passed the callback check,
1985
+ * else `undefined`.
2077
1986
  * @example
2078
1987
  *
2079
1988
  * var even = _.find([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
2080
1989
  * // => 2
2081
1990
  */
2082
1991
  var find = createIterator(baseIteratorOptions, forEachIteratorOptions, {
2083
- 'init': '',
1992
+ 'init': false,
2084
1993
  'inLoop': 'if (callback(value, index, collection)) return value'
2085
1994
  });
2086
1995
 
2087
1996
  /**
2088
1997
  * Iterates over a `collection`, executing the `callback` for each element in
2089
- * the `collection`. The `callback` is bound to `thisArg` and invoked with 3
2090
- * arguments; (value, index|key, collection). Callbacks may exit iteration
2091
- * early by explicitly returning `false`.
1998
+ * the `collection`. The `callback` is bound to `thisArg` and invoked with three
1999
+ * arguments; (value, index|key, collection). Callbacks may exit iteration early
2000
+ * by explicitly returning `false`.
2092
2001
  *
2093
2002
  * @static
2094
2003
  * @memberOf _
@@ -2096,8 +2005,8 @@
2096
2005
  * @category Collections
2097
2006
  * @param {Array|Object|String} collection The collection to iterate over.
2098
2007
  * @param {Function} callback The function called per iteration.
2099
- * @param {Mixed} [thisArg] The `this` binding for the callback.
2100
- * @returns {Array|Object} Returns `collection`.
2008
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
2009
+ * @returns {Array|Object|String} Returns `collection`.
2101
2010
  * @example
2102
2011
  *
2103
2012
  * _([1, 2, 3]).forEach(alert).join(',');
@@ -2112,7 +2021,7 @@
2112
2021
  * Creates an object composed of keys returned from running each element of
2113
2022
  * `collection` through a `callback`. The corresponding value of each key is an
2114
2023
  * array of elements passed to `callback` that returned the key. The `callback`
2115
- * is bound to `thisArg` and invoked with 3 arguments; (value, index|key, collection).
2024
+ * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
2116
2025
  * The `callback` argument may also be the name of a property to count by (e.g. 'length').
2117
2026
  *
2118
2027
  * @static
@@ -2121,7 +2030,7 @@
2121
2030
  * @param {Array|Object|String} collection The collection to iterate over.
2122
2031
  * @param {Function|String} callback|property The function called per iteration
2123
2032
  * or property name to group by.
2124
- * @param {Mixed} [thisArg] The `this` binding for the callback.
2033
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
2125
2034
  * @returns {Object} Returns the composed aggregate object.
2126
2035
  * @example
2127
2036
  *
@@ -2136,15 +2045,15 @@
2136
2045
  */
2137
2046
  var groupBy = createIterator(baseIteratorOptions, countByIteratorOptions, {
2138
2047
  'inLoop':
2139
- 'prop = callback(value, index, collection);\n' +
2048
+ 'var prop = callback(value, index, collection);\n' +
2140
2049
  '(hasOwnProperty.call(result, prop) ? result[prop] : result[prop] = []).push(value)'
2141
2050
  });
2142
2051
 
2143
2052
  /**
2144
- * Invokes the method named by `methodName` on each element in the `collection`.
2145
- * Additional arguments will be passed to each invoked method. If `methodName`
2146
- * is a function it will be invoked for, and `this` bound to, each element
2147
- * in the `collection`.
2053
+ * Invokes the method named by `methodName` on each element in the `collection`,
2054
+ * returning an array of the results of each invoked method. Additional arguments
2055
+ * will be passed to each invoked method. If `methodName` is a function it will
2056
+ * be invoked for, and `this` bound to, each element in the `collection`.
2148
2057
  *
2149
2058
  * @static
2150
2059
  * @memberOf _
@@ -2153,7 +2062,7 @@
2153
2062
  * @param {Function|String} methodName The name of the method to invoke or
2154
2063
  * the function invoked per iteration.
2155
2064
  * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with.
2156
- * @returns {Array} Returns a new array of values returned from each invoked method.
2065
+ * @returns {Array} Returns a new array of the results of each invoked method.
2157
2066
  * @example
2158
2067
  *
2159
2068
  * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
@@ -2177,9 +2086,9 @@
2177
2086
  });
2178
2087
 
2179
2088
  /**
2180
- * Creates a new array of values by running each element in the `collection`
2089
+ * Creates an array of values by running each element in the `collection`
2181
2090
  * through a `callback`. The `callback` is bound to `thisArg` and invoked with
2182
- * 3 arguments; (value, index|key, collection).
2091
+ * three arguments; (value, index|key, collection).
2183
2092
  *
2184
2093
  * @static
2185
2094
  * @memberOf _
@@ -2187,8 +2096,8 @@
2187
2096
  * @category Collections
2188
2097
  * @param {Array|Object|String} collection The collection to iterate over.
2189
2098
  * @param {Function} [callback=identity] The function called per iteration.
2190
- * @param {Mixed} [thisArg] The `this` binding for the callback.
2191
- * @returns {Array} Returns a new array of elements returned by the callback.
2099
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
2100
+ * @returns {Array} Returns a new array of the results of each `callback` execution.
2192
2101
  * @example
2193
2102
  *
2194
2103
  * _.map([1, 2, 3], function(num) { return num * 3; });
@@ -2241,7 +2150,7 @@
2241
2150
  * @param {Array|Object|String} collection The collection to iterate over.
2242
2151
  * @param {Function} callback The function called per iteration.
2243
2152
  * @param {Mixed} [accumulator] Initial value of the accumulator.
2244
- * @param {Mixed} [thisArg] The `this` binding for the callback.
2153
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
2245
2154
  * @returns {Mixed} Returns the accumulated value.
2246
2155
  * @example
2247
2156
  *
@@ -2253,7 +2162,7 @@
2253
2162
  'init': 'accumulator',
2254
2163
  'top':
2255
2164
  'var noaccum = arguments.length < 3;\n' +
2256
- 'if (thisArg) callback = iteratorBind(callback, thisArg)',
2165
+ 'callback = createCallback(callback, thisArg)',
2257
2166
  'beforeLoop': {
2258
2167
  'array': 'if (noaccum) result = iteratee[++index]'
2259
2168
  },
@@ -2277,7 +2186,7 @@
2277
2186
  * @param {Array|Object|String} collection The collection to iterate over.
2278
2187
  * @param {Function} callback The function called per iteration.
2279
2188
  * @param {Mixed} [accumulator] Initial value of the accumulator.
2280
- * @param {Mixed} [thisArg] The `this` binding for the callback.
2189
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
2281
2190
  * @returns {Mixed} Returns the accumulated value.
2282
2191
  * @example
2283
2192
  *
@@ -2286,42 +2195,22 @@
2286
2195
  * // => [4, 5, 2, 3, 0, 1]
2287
2196
  */
2288
2197
  function reduceRight(collection, callback, accumulator, thisArg) {
2289
- if (!collection) {
2290
- return accumulator;
2291
- }
2292
-
2293
- var length = collection.length,
2198
+ var iteratee = collection,
2199
+ length = collection ? collection.length : 0,
2294
2200
  noaccum = arguments.length < 3;
2295
2201
 
2296
- if(thisArg) {
2297
- callback = iteratorBind(callback, thisArg);
2298
- }
2299
- // Opera 10.53-10.60 JITted `length >>> 0` returns the wrong value for negative numbers
2300
- if (length > -1 && length === length >>> 0) {
2301
- var iteratee = noCharByIndex && toString.call(collection) == stringClass
2302
- ? collection.split('')
2303
- : collection;
2304
-
2305
- if (length && noaccum) {
2306
- accumulator = iteratee[--length];
2307
- }
2308
- while (length--) {
2309
- accumulator = callback(accumulator, iteratee[length], length, collection);
2310
- }
2311
- return accumulator;
2312
- }
2313
-
2314
- var prop,
2315
- props = keys(collection);
2316
-
2317
- length = props.length;
2318
- if (length && noaccum) {
2319
- accumulator = collection[props[--length]];
2320
- }
2321
- while (length--) {
2322
- prop = props[length];
2323
- accumulator = callback(accumulator, collection[prop], prop, collection);
2202
+ if (length !== +length) {
2203
+ var props = keys(collection);
2204
+ length = props.length;
2205
+ } else if (noCharByIndex && toString.call(collection) == stringClass) {
2206
+ iteratee = collection.split('');
2324
2207
  }
2208
+ forEach(collection, function(value, index, object) {
2209
+ index = props ? props[--length] : --length;
2210
+ accumulator = noaccum
2211
+ ? (noaccum = false, iteratee[index])
2212
+ : callback.call(thisArg, accumulator, iteratee[index], index, object);
2213
+ });
2325
2214
  return accumulator;
2326
2215
  }
2327
2216
 
@@ -2334,8 +2223,9 @@
2334
2223
  * @category Collections
2335
2224
  * @param {Array|Object|String} collection The collection to iterate over.
2336
2225
  * @param {Function} [callback=identity] The function called per iteration.
2337
- * @param {Mixed} [thisArg] The `this` binding for the callback.
2338
- * @returns {Array} Returns a new array of elements that did **not** pass the callback check.
2226
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
2227
+ * @returns {Array} Returns a new array of elements that did **not** pass the
2228
+ * callback check.
2339
2229
  * @example
2340
2230
  *
2341
2231
  * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
@@ -2366,18 +2256,15 @@
2366
2256
  * // => 5
2367
2257
  */
2368
2258
  function size(collection) {
2369
- if (!collection) {
2370
- return 0;
2371
- }
2372
- var length = collection.length;
2373
- return length > -1 && length === length >>> 0 ? length : keys(collection).length;
2259
+ var length = collection ? collection.length : 0;
2260
+ return length === +length ? length : keys(collection).length;
2374
2261
  }
2375
2262
 
2376
2263
  /**
2377
2264
  * Checks if the `callback` returns a truthy value for **any** element of a
2378
2265
  * `collection`. The function returns as soon as it finds passing value, and
2379
2266
  * does not iterate over the entire `collection`. The `callback` is bound to
2380
- * `thisArg` and invoked with 3 arguments; (value, index|key, collection).
2267
+ * `thisArg` and invoked with three arguments; (value, index|key, collection).
2381
2268
  *
2382
2269
  * @static
2383
2270
  * @memberOf _
@@ -2385,8 +2272,9 @@
2385
2272
  * @category Collections
2386
2273
  * @param {Array|Object|String} collection The collection to iterate over.
2387
2274
  * @param {Function} [callback=identity] The function called per iteration.
2388
- * @param {Mixed} [thisArg] The `this` binding for the callback.
2389
- * @returns {Boolean} Returns `true` if any element passes the callback check, else `false`.
2275
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
2276
+ * @returns {Boolean} Returns `true` if any element passes the callback check,
2277
+ * else `false`.
2390
2278
  * @example
2391
2279
  *
2392
2280
  * _.some([null, 0, 'yes', false]);
@@ -2398,9 +2286,9 @@
2398
2286
  });
2399
2287
 
2400
2288
  /**
2401
- * Creates a new array, stable sorted in ascending order by the results of
2289
+ * Creates an array, stable sorted in ascending order by the results of
2402
2290
  * running each element of `collection` through a `callback`. The `callback`
2403
- * is bound to `thisArg` and invoked with 3 arguments; (value, index|key, collection).
2291
+ * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
2404
2292
  * The `callback` argument may also be the name of a property to sort by (e.g. 'length').
2405
2293
  *
2406
2294
  * @static
@@ -2409,7 +2297,7 @@
2409
2297
  * @param {Array|Object|String} collection The collection to iterate over.
2410
2298
  * @param {Function|String} callback|property The function called per iteration
2411
2299
  * or property name to sort by.
2412
- * @param {Mixed} [thisArg] The `this` binding for the callback.
2300
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
2413
2301
  * @returns {Array} Returns a new array of sorted elements.
2414
2302
  * @example
2415
2303
  *
@@ -2446,8 +2334,7 @@
2446
2334
  });
2447
2335
 
2448
2336
  /**
2449
- * Converts the `collection`, to an array. Useful for converting the
2450
- * `arguments` object.
2337
+ * Converts the `collection`, to an array.
2451
2338
  *
2452
2339
  * @static
2453
2340
  * @memberOf _
@@ -2463,11 +2350,8 @@
2463
2350
  if (!collection) {
2464
2351
  return [];
2465
2352
  }
2466
- if (collection.toArray && isFunction(collection.toArray)) {
2467
- return collection.toArray();
2468
- }
2469
2353
  var length = collection.length;
2470
- if (length > -1 && length === length >>> 0) {
2354
+ if (length === +length) {
2471
2355
  return (noArraySliceOnStrings ? toString.call(collection) == stringClass : typeof collection == 'string')
2472
2356
  ? collection.split('')
2473
2357
  : slice.call(collection);
@@ -2513,7 +2397,7 @@
2513
2397
  /*--------------------------------------------------------------------------*/
2514
2398
 
2515
2399
  /**
2516
- * Creates a new array with all falsey values of `array` removed. The values
2400
+ * Creates an array with all falsey values of `array` removed. The values
2517
2401
  * `false`, `null`, `0`, `""`, `undefined` and `NaN` are all falsey.
2518
2402
  *
2519
2403
  * @static
@@ -2527,12 +2411,9 @@
2527
2411
  * // => [1, 2, 3]
2528
2412
  */
2529
2413
  function compact(array) {
2530
- var result = [];
2531
- if (!array) {
2532
- return result;
2533
- }
2534
2414
  var index = -1,
2535
- length = array.length;
2415
+ length = array ? array.length : 0,
2416
+ result = [];
2536
2417
 
2537
2418
  while (++index < length) {
2538
2419
  if (array[index]) {
@@ -2543,7 +2424,7 @@
2543
2424
  }
2544
2425
 
2545
2426
  /**
2546
- * Creates a new array of `array` elements not present in the other arrays
2427
+ * Creates an array of `array` elements not present in the other arrays
2547
2428
  * using strict equality for comparisons, i.e. `===`.
2548
2429
  *
2549
2430
  * @static
@@ -2565,12 +2446,13 @@
2565
2446
  }
2566
2447
  var index = -1,
2567
2448
  length = array.length,
2568
- flattened = concat.apply(result, arguments),
2449
+ flattened = concat.apply(ArrayProto, arguments),
2569
2450
  contains = cachedContains(flattened, length);
2570
2451
 
2571
2452
  while (++index < length) {
2572
- if (!contains(array[index])) {
2573
- result.push(array[index]);
2453
+ var value = array[index];
2454
+ if (!contains(value)) {
2455
+ result.push(value);
2574
2456
  }
2575
2457
  }
2576
2458
  return result;
@@ -2586,7 +2468,7 @@
2586
2468
  * @category Arrays
2587
2469
  * @param {Array} array The array to query.
2588
2470
  * @param {Number} [n] The number of elements to return.
2589
- * @param {Object} [guard] Internally used to allow this method to work with
2471
+ * @param- {Object} [guard] Internally used to allow this method to work with
2590
2472
  * others like `_.map` without using their callback `index` argument for `n`.
2591
2473
  * @returns {Mixed} Returns the first element or an array of the first `n`
2592
2474
  * elements of `array`.
@@ -2620,16 +2502,15 @@
2620
2502
  * // => [1, 2, 3, [[4]]];
2621
2503
  */
2622
2504
  function flatten(array, shallow) {
2623
- var result = [];
2624
- if (!array) {
2625
- return result;
2626
- }
2627
2505
  var value,
2628
2506
  index = -1,
2629
- length = array.length;
2507
+ length = array ? array.length : 0,
2508
+ result = [];
2630
2509
 
2631
2510
  while (++index < length) {
2632
2511
  value = array[index];
2512
+
2513
+ // recursively flatten arrays (susceptible to call stack limits)
2633
2514
  if (isArray(value)) {
2634
2515
  push.apply(result, shallow ? value : flatten(value));
2635
2516
  } else {
@@ -2664,19 +2545,14 @@
2664
2545
  * // => 2
2665
2546
  */
2666
2547
  function indexOf(array, value, fromIndex) {
2667
- if (!array) {
2668
- return -1;
2669
- }
2670
2548
  var index = -1,
2671
- length = array.length;
2549
+ length = array ? array.length : 0;
2672
2550
 
2673
- if (fromIndex) {
2674
- if (typeof fromIndex == 'number') {
2675
- index = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) - 1;
2676
- } else {
2677
- index = sortedIndex(array, value);
2678
- return array[index] === value ? index : -1;
2679
- }
2551
+ if (typeof fromIndex == 'number') {
2552
+ index = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0) - 1;
2553
+ } else if (fromIndex) {
2554
+ index = sortedIndex(array, value);
2555
+ return array[index] === value ? index : -1;
2680
2556
  }
2681
2557
  while (++index < length) {
2682
2558
  if (array[index] === value) {
@@ -2695,7 +2571,7 @@
2695
2571
  * @category Arrays
2696
2572
  * @param {Array} array The array to query.
2697
2573
  * @param {Number} [n] The number of elements to return.
2698
- * @param {Object} [guard] Internally used to allow this method to work with
2574
+ * @param- {Object} [guard] Internally used to allow this method to work with
2699
2575
  * others like `_.map` without using their callback `index` argument for `n`.
2700
2576
  * @returns {Array} Returns all but the last element or `n` elements of `array`.
2701
2577
  * @example
@@ -2704,10 +2580,9 @@
2704
2580
  * // => [3, 2]
2705
2581
  */
2706
2582
  function initial(array, n, guard) {
2707
- if (!array) {
2708
- return [];
2709
- }
2710
- return slice.call(array, 0, -((n == null || guard) ? 1 : n));
2583
+ return array
2584
+ ? slice.call(array, 0, -((n == null || guard) ? 1 : n))
2585
+ : [];
2711
2586
  }
2712
2587
 
2713
2588
  /**
@@ -2726,18 +2601,14 @@
2726
2601
  * // => [1, 2]
2727
2602
  */
2728
2603
  function intersection(array) {
2729
- var result = [];
2730
- if (!array) {
2731
- return result;
2732
- }
2733
- var value,
2734
- argsLength = arguments.length,
2604
+ var argsLength = arguments.length,
2735
2605
  cache = [],
2736
2606
  index = -1,
2737
- length = array.length;
2607
+ length = array ? array.length : 0,
2608
+ result = [];
2738
2609
 
2739
2610
  array: while (++index < length) {
2740
- value = array[index];
2611
+ var value = array[index];
2741
2612
  if (indexOf(result, value) < 0) {
2742
2613
  for (var argsIndex = 1; argsIndex < argsLength; argsIndex++) {
2743
2614
  if (!(cache[argsIndex] || (cache[argsIndex] = cachedContains(arguments[argsIndex])))(value)) {
@@ -2751,15 +2622,15 @@
2751
2622
  }
2752
2623
 
2753
2624
  /**
2754
- * Gets the last element of the `array`. Pass `n` to return the lasy `n`
2755
- * elementsvof the `array`.
2625
+ * Gets the last element of the `array`. Pass `n` to return the last `n`
2626
+ * elements of the `array`.
2756
2627
  *
2757
2628
  * @static
2758
2629
  * @memberOf _
2759
2630
  * @category Arrays
2760
2631
  * @param {Array} array The array to query.
2761
2632
  * @param {Number} [n] The number of elements to return.
2762
- * @param {Object} [guard] Internally used to allow this method to work with
2633
+ * @param- {Object} [guard] Internally used to allow this method to work with
2763
2634
  * others like `_.map` without using their callback `index` argument for `n`.
2764
2635
  * @returns {Mixed} Returns the last element or an array of the last `n`
2765
2636
  * elements of `array`.
@@ -2795,11 +2666,8 @@
2795
2666
  * // => 1
2796
2667
  */
2797
2668
  function lastIndexOf(array, value, fromIndex) {
2798
- if (!array) {
2799
- return -1;
2800
- }
2801
- var index = array.length;
2802
- if (fromIndex && typeof fromIndex == 'number') {
2669
+ var index = array ? array.length : 0;
2670
+ if (typeof fromIndex == 'number') {
2803
2671
  index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1;
2804
2672
  }
2805
2673
  while (index--) {
@@ -2814,14 +2682,14 @@
2814
2682
  * Retrieves the maximum value of an `array`. If `callback` is passed,
2815
2683
  * it will be executed for each value in the `array` to generate the
2816
2684
  * criterion by which the value is ranked. The `callback` is bound to
2817
- * `thisArg` and invoked with 3 arguments; (value, index, array).
2685
+ * `thisArg` and invoked with three arguments; (value, index, array).
2818
2686
  *
2819
2687
  * @static
2820
2688
  * @memberOf _
2821
2689
  * @category Arrays
2822
2690
  * @param {Array} array The array to iterate over.
2823
2691
  * @param {Function} [callback] The function called per iteration.
2824
- * @param {Mixed} [thisArg] The `this` binding for the callback.
2692
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
2825
2693
  * @returns {Mixed} Returns the maximum value.
2826
2694
  * @example
2827
2695
  *
@@ -2835,27 +2703,13 @@
2835
2703
  * // => { 'name': 'curly', 'age': 60 };
2836
2704
  */
2837
2705
  function max(array, callback, thisArg) {
2838
- var computed = -Infinity,
2839
- result = computed;
2840
-
2841
- if (!array) {
2842
- return result;
2843
- }
2844
2706
  var current,
2707
+ computed = -Infinity,
2845
2708
  index = -1,
2846
- length = array.length;
2709
+ length = array ? array.length : 0,
2710
+ result = computed;
2847
2711
 
2848
- if (!callback) {
2849
- while (++index < length) {
2850
- if (array[index] > result) {
2851
- result = array[index];
2852
- }
2853
- }
2854
- return result;
2855
- }
2856
- if (thisArg) {
2857
- callback = iteratorBind(callback, thisArg);
2858
- }
2712
+ callback = createCallback(callback, thisArg);
2859
2713
  while (++index < length) {
2860
2714
  current = callback(array[index], index, array);
2861
2715
  if (current > computed) {
@@ -2870,14 +2724,14 @@
2870
2724
  * Retrieves the minimum value of an `array`. If `callback` is passed,
2871
2725
  * it will be executed for each value in the `array` to generate the
2872
2726
  * criterion by which the value is ranked. The `callback` is bound to `thisArg`
2873
- * and invoked with 3 arguments; (value, index, array).
2727
+ * and invoked with three arguments; (value, index, array).
2874
2728
  *
2875
2729
  * @static
2876
2730
  * @memberOf _
2877
2731
  * @category Arrays
2878
2732
  * @param {Array} array The array to iterate over.
2879
2733
  * @param {Function} [callback] The function called per iteration.
2880
- * @param {Mixed} [thisArg] The `this` binding for the callback.
2734
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
2881
2735
  * @returns {Mixed} Returns the minimum value.
2882
2736
  * @example
2883
2737
  *
@@ -2885,27 +2739,13 @@
2885
2739
  * // => 2
2886
2740
  */
2887
2741
  function min(array, callback, thisArg) {
2888
- var computed = Infinity,
2889
- result = computed;
2890
-
2891
- if (!array) {
2892
- return result;
2893
- }
2894
2742
  var current,
2743
+ computed = Infinity,
2895
2744
  index = -1,
2896
- length = array.length;
2745
+ length = array ? array.length : 0,
2746
+ result = computed;
2897
2747
 
2898
- if (!callback) {
2899
- while (++index < length) {
2900
- if (array[index] < result) {
2901
- result = array[index];
2902
- }
2903
- }
2904
- return result;
2905
- }
2906
- if (thisArg) {
2907
- callback = iteratorBind(callback, thisArg);
2908
- }
2748
+ callback = createCallback(callback, thisArg);
2909
2749
  while (++index < length) {
2910
2750
  current = callback(array[index], index, array);
2911
2751
  if (current < computed) {
@@ -2934,11 +2774,8 @@
2934
2774
  * // => { 'moe': 30, 'larry': 40, 'curly': 50 }
2935
2775
  */
2936
2776
  function object(keys, values) {
2937
- if (!keys) {
2938
- return {};
2939
- }
2940
2777
  var index = -1,
2941
- length = keys.length,
2778
+ length = keys ? keys.length : 0,
2942
2779
  result = {};
2943
2780
 
2944
2781
  while (++index < length) {
@@ -3011,7 +2848,7 @@
3011
2848
  * @category Arrays
3012
2849
  * @param {Array} array The array to query.
3013
2850
  * @param {Number} [n] The number of elements to return.
3014
- * @param {Object} [guard] Internally used to allow this method to work with
2851
+ * @param- {Object} [guard] Internally used to allow this method to work with
3015
2852
  * others like `_.map` without using their callback `index` argument for `n`.
3016
2853
  * @returns {Array} Returns all but the first value or `n` values of `array`.
3017
2854
  * @example
@@ -3020,14 +2857,13 @@
3020
2857
  * // => [2, 1]
3021
2858
  */
3022
2859
  function rest(array, n, guard) {
3023
- if (!array) {
3024
- return [];
3025
- }
3026
- return slice.call(array, (n == null || guard) ? 1 : n);
2860
+ return array
2861
+ ? slice.call(array, (n == null || guard) ? 1 : n)
2862
+ : [];
3027
2863
  }
3028
2864
 
3029
2865
  /**
3030
- * Creates a new array of shuffled `array` values, using a version of the
2866
+ * Creates an array of shuffled `array` values, using a version of the
3031
2867
  * Fisher-Yates shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
3032
2868
  *
3033
2869
  * @static
@@ -3041,16 +2877,12 @@
3041
2877
  * // => [4, 1, 6, 3, 5, 2]
3042
2878
  */
3043
2879
  function shuffle(array) {
3044
- if (!array) {
3045
- return [];
3046
- }
3047
- var rand,
3048
- index = -1,
3049
- length = array.length,
2880
+ var index = -1,
2881
+ length = array ? array.length : 0,
3050
2882
  result = Array(length);
3051
2883
 
3052
2884
  while (++index < length) {
3053
- rand = nativeFloor(nativeRandom() * (index + 1));
2885
+ var rand = nativeFloor(nativeRandom() * (index + 1));
3054
2886
  result[index] = result[rand];
3055
2887
  result[rand] = array[index];
3056
2888
  }
@@ -3062,58 +2894,50 @@
3062
2894
  * should be inserted into `array` in order to maintain the sort order of the
3063
2895
  * sorted `array`. If `callback` is passed, it will be executed for `value` and
3064
2896
  * each element in `array` to compute their sort ranking. The `callback` is
3065
- * bound to `thisArg` and invoked with 1 argument; (value).
2897
+ * bound to `thisArg` and invoked with one argument; (value). The `callback`
2898
+ * argument may also be the name of a property to order by.
3066
2899
  *
3067
2900
  * @static
3068
2901
  * @memberOf _
3069
2902
  * @category Arrays
3070
2903
  * @param {Array} array The array to iterate over.
3071
2904
  * @param {Mixed} value The value to evaluate.
3072
- * @param {Function} [callback=identity] The function called per iteration.
3073
- * @param {Mixed} [thisArg] The `this` binding for the callback.
2905
+ * @param {Function|String} [callback=identity|property] The function called
2906
+ * per iteration or property name to order by.
2907
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
3074
2908
  * @returns {Number} Returns the index at which the value should be inserted
3075
2909
  * into `array`.
3076
2910
  * @example
3077
2911
  *
3078
- * _.sortedIndex([20, 30, 40], 35);
2912
+ * _.sortedIndex([20, 30, 50], 40);
2913
+ * // => 2
2914
+ *
2915
+ * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
3079
2916
  * // => 2
3080
2917
  *
3081
2918
  * var dict = {
3082
- * 'wordToNumber': { 'twenty': 20, 'thirty': 30, 'thirty-five': 35, 'fourty': 40 }
2919
+ * 'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 }
3083
2920
  * };
3084
2921
  *
3085
- * _.sortedIndex(['twenty', 'thirty', 'fourty'], 'thirty-five', function(word) {
2922
+ * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
3086
2923
  * return dict.wordToNumber[word];
3087
2924
  * });
3088
2925
  * // => 2
3089
2926
  *
3090
- * _.sortedIndex(['twenty', 'thirty', 'fourty'], 'thirty-five', function(word) {
2927
+ * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
3091
2928
  * return this.wordToNumber[word];
3092
2929
  * }, dict);
3093
2930
  * // => 2
3094
2931
  */
3095
2932
  function sortedIndex(array, value, callback, thisArg) {
3096
- if (!array) {
3097
- return 0;
3098
- }
3099
- var mid,
3100
- low = 0,
3101
- high = array.length;
3102
-
3103
- if (callback) {
3104
- if (thisArg) {
3105
- callback = bind(callback, thisArg);
3106
- }
3107
- value = callback(value);
3108
- while (low < high) {
3109
- mid = (low + high) >>> 1;
3110
- callback(array[mid]) < value ? low = mid + 1 : high = mid;
3111
- }
3112
- } else {
3113
- while (low < high) {
3114
- mid = (low + high) >>> 1;
3115
- array[mid] < value ? low = mid + 1 : high = mid;
3116
- }
2933
+ var low = 0,
2934
+ high = array ? array.length : low;
2935
+
2936
+ callback = createCallback(callback, thisArg);
2937
+ value = callback(value);
2938
+ while (low < high) {
2939
+ var mid = (low + high) >>> 1;
2940
+ callback(array[mid]) < value ? low = mid + 1 : high = mid;
3117
2941
  }
3118
2942
  return low;
3119
2943
  }
@@ -3135,9 +2959,9 @@
3135
2959
  */
3136
2960
  function union() {
3137
2961
  var index = -1,
3138
- result = [],
3139
- flattened = concat.apply(result, arguments),
3140
- length = flattened.length;
2962
+ flattened = concat.apply(ArrayProto, arguments),
2963
+ length = flattened.length,
2964
+ result = [];
3141
2965
 
3142
2966
  while (++index < length) {
3143
2967
  if (indexOf(result, flattened[index]) < 0) {
@@ -3152,7 +2976,7 @@
3152
2976
  * for comparisons, i.e. `===`. If the `array` is already sorted, passing `true`
3153
2977
  * for `isSorted` will run a faster algorithm. If `callback` is passed, each
3154
2978
  * element of `array` is passed through a callback` before uniqueness is computed.
3155
- * The `callback` is bound to `thisArg` and invoked with 3 arguments; (value, index, array).
2979
+ * The `callback` is bound to `thisArg` and invoked with three arguments; (value, index, array).
3156
2980
  *
3157
2981
  * @static
3158
2982
  * @memberOf _
@@ -3161,7 +2985,7 @@
3161
2985
  * @param {Array} array The array to process.
3162
2986
  * @param {Boolean} [isSorted=false] A flag to indicate that the `array` is already sorted.
3163
2987
  * @param {Function} [callback=identity] The function called per iteration.
3164
- * @param {Mixed} [thisArg] The `this` binding for the callback.
2988
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
3165
2989
  * @returns {Array} Returns a duplicate-value-free array.
3166
2990
  * @example
3167
2991
  *
@@ -3178,13 +3002,9 @@
3178
3002
  * // => [1, 2, 3]
3179
3003
  */
3180
3004
  function uniq(array, isSorted, callback, thisArg) {
3181
- var result = [];
3182
- if (!array) {
3183
- return result;
3184
- }
3185
- var computed,
3186
- index = -1,
3187
- length = array.length,
3005
+ var index = -1,
3006
+ length = array ? array.length : 0,
3007
+ result = [],
3188
3008
  seen = [];
3189
3009
 
3190
3010
  // juggle arguments
@@ -3193,13 +3013,9 @@
3193
3013
  callback = isSorted;
3194
3014
  isSorted = false;
3195
3015
  }
3196
- if (!callback) {
3197
- callback = identity;
3198
- } else if (thisArg) {
3199
- callback = iteratorBind(callback, thisArg);
3200
- }
3016
+ callback = createCallback(callback, thisArg);
3201
3017
  while (++index < length) {
3202
- computed = callback(array[index], index, array);
3018
+ var computed = callback(array[index], index, array);
3203
3019
  if (isSorted
3204
3020
  ? !index || seen[seen.length - 1] !== computed
3205
3021
  : indexOf(seen, computed) < 0
@@ -3212,7 +3028,7 @@
3212
3028
  }
3213
3029
 
3214
3030
  /**
3215
- * Creates a new array with all occurrences of the passed values removed using
3031
+ * Creates an array with all occurrences of the passed values removed using
3216
3032
  * strict equality for comparisons, i.e. `===`.
3217
3033
  *
3218
3034
  * @static
@@ -3227,17 +3043,15 @@
3227
3043
  * // => [2, 3, 4]
3228
3044
  */
3229
3045
  function without(array) {
3230
- var result = [];
3231
- if (!array) {
3232
- return result;
3233
- }
3234
3046
  var index = -1,
3235
- length = array.length,
3236
- contains = cachedContains(arguments, 1, 20);
3047
+ length = array ? array.length : 0,
3048
+ contains = cachedContains(arguments, 1, 20),
3049
+ result = [];
3237
3050
 
3238
3051
  while (++index < length) {
3239
- if (!contains(array[index])) {
3240
- result.push(array[index]);
3052
+ var value = array[index];
3053
+ if (!contains(value)) {
3054
+ result.push(value);
3241
3055
  }
3242
3056
  }
3243
3057
  return result;
@@ -3260,11 +3074,8 @@
3260
3074
  * // => [['moe', 30, true], ['larry', 40, false], ['curly', 50, false]]
3261
3075
  */
3262
3076
  function zip(array) {
3263
- if (!array) {
3264
- return [];
3265
- }
3266
3077
  var index = -1,
3267
- length = max(pluck(arguments, 'length')),
3078
+ length = array ? max(pluck(arguments, 'length')) : 0,
3268
3079
  result = Array(length);
3269
3080
 
3270
3081
  while (++index < length) {
@@ -3276,7 +3087,7 @@
3276
3087
  /*--------------------------------------------------------------------------*/
3277
3088
 
3278
3089
  /**
3279
- * Creates a new function that is restricted to executing only after it is
3090
+ * Creates a function that is restricted to executing only after it is
3280
3091
  * called `n` times.
3281
3092
  *
3282
3093
  * @static
@@ -3306,21 +3117,19 @@
3306
3117
  }
3307
3118
 
3308
3119
  /**
3309
- * Creates a new function that, when called, invokes `func` with the `this`
3120
+ * Creates a function that, when called, invokes `func` with the `this`
3310
3121
  * binding of `thisArg` and prepends any additional `bind` arguments to those
3311
- * passed to the bound function. Lazy defined methods may be bound by passing
3312
- * the object they are bound to as `func` and the method name as `thisArg`.
3122
+ * passed to the bound function.
3313
3123
  *
3314
3124
  * @static
3315
3125
  * @memberOf _
3316
3126
  * @category Functions
3317
- * @param {Function|Object} func The function to bind or the object the method belongs to.
3318
- * @param {Mixed} [thisArg] The `this` binding of `func` or the method name.
3127
+ * @param {Function} func The function to bind.
3128
+ * @param {Mixed} [thisArg] The `this` binding of `func`.
3319
3129
  * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
3320
3130
  * @returns {Function} Returns the new bound function.
3321
3131
  * @example
3322
3132
  *
3323
- * // basic bind
3324
3133
  * var func = function(greeting) {
3325
3134
  * return greeting + ' ' + this.name;
3326
3135
  * };
@@ -3328,72 +3137,13 @@
3328
3137
  * func = _.bind(func, { 'name': 'moe' }, 'hi');
3329
3138
  * func();
3330
3139
  * // => 'hi moe'
3331
- *
3332
- * // lazy bind
3333
- * var object = {
3334
- * 'name': 'moe',
3335
- * 'greet': function(greeting) {
3336
- * return greeting + ' ' + this.name;
3337
- * }
3338
- * };
3339
- *
3340
- * var func = _.bind(object, 'greet', 'hi');
3341
- * func();
3342
- * // => 'hi moe'
3343
- *
3344
- * object.greet = function(greeting) {
3345
- * return greeting + ', ' + this.name + '!';
3346
- * };
3347
- *
3348
- * func();
3349
- * // => 'hi, moe!'
3350
3140
  */
3351
3141
  function bind(func, thisArg) {
3352
- var methodName,
3353
- isFunc = isFunction(func);
3354
-
3355
- // juggle arguments
3356
- if (!isFunc) {
3357
- methodName = thisArg;
3358
- thisArg = func;
3359
- }
3360
3142
  // use `Function#bind` if it exists and is fast
3361
3143
  // (in V8 `Function#bind` is slower except when partially applied)
3362
- else if (isBindFast || (nativeBind && arguments.length > 2)) {
3363
- return nativeBind.call.apply(nativeBind, arguments);
3364
- }
3365
-
3366
- var partialArgs = slice.call(arguments, 2);
3367
-
3368
- function bound() {
3369
- // `Function#bind` spec
3370
- // http://es5.github.com/#x15.3.4.5
3371
- var args = arguments,
3372
- thisBinding = thisArg;
3373
-
3374
- if (!isFunc) {
3375
- func = thisArg[methodName];
3376
- }
3377
- if (partialArgs.length) {
3378
- args = args.length
3379
- ? partialArgs.concat(slice.call(args))
3380
- : partialArgs;
3381
- }
3382
- if (this instanceof bound) {
3383
- // get `func` instance if `bound` is invoked in a `new` expression
3384
- noop.prototype = func.prototype;
3385
- thisBinding = new noop;
3386
-
3387
- // mimic the constructor's `return` behavior
3388
- // http://es5.github.com/#x13.2.2
3389
- var result = func.apply(thisBinding, args);
3390
- return result && objectTypes[typeof result]
3391
- ? result
3392
- : thisBinding
3393
- }
3394
- return func.apply(thisBinding, args);
3395
- }
3396
- return bound;
3144
+ return isBindFast || (nativeBind && arguments.length > 2)
3145
+ ? nativeBind.call.apply(nativeBind, arguments)
3146
+ : createBound(func, thisArg, slice.call(arguments, 2));
3397
3147
  }
3398
3148
 
3399
3149
  /**
@@ -3422,7 +3172,6 @@
3422
3172
  'useHas': false,
3423
3173
  'useStrict': false,
3424
3174
  'args': 'object',
3425
- 'init': 'object',
3426
3175
  'top':
3427
3176
  'var funcs = arguments,\n' +
3428
3177
  ' length = funcs.length;\n' +
@@ -3433,13 +3182,13 @@
3433
3182
  ' return result\n' +
3434
3183
  '}',
3435
3184
  'inLoop':
3436
- 'if (isFunction(result[index])) {\n' +
3437
- ' result[index] = bind(result[index], result)\n' +
3185
+ 'if (isFunction(value)) {\n' +
3186
+ ' result[index] = bind(value, result)\n' +
3438
3187
  '}'
3439
3188
  });
3440
3189
 
3441
3190
  /**
3442
- * Creates a new function that is the composition of the passed functions,
3191
+ * Creates a function that is the composition of the passed functions,
3443
3192
  * where each function consumes the return value of the function that follows.
3444
3193
  * In math terms, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
3445
3194
  *
@@ -3470,7 +3219,7 @@
3470
3219
  }
3471
3220
 
3472
3221
  /**
3473
- * Creates a new function that will delay the execution of `func` until after
3222
+ * Creates a function that will delay the execution of `func` until after
3474
3223
  * `wait` milliseconds have elapsed since the last time it was invoked. Pass
3475
3224
  * `true` for `immediate` to cause debounce to invoke `func` on the leading,
3476
3225
  * instead of the trailing, edge of the `wait` timeout. Subsequent calls to
@@ -3560,7 +3309,44 @@
3560
3309
  }
3561
3310
 
3562
3311
  /**
3563
- * Creates a new function that memoizes the result of `func`. If `resolver` is
3312
+ * Creates a function that, when called, invokes `object[methodName]` and
3313
+ * prepends any additional `lateBind` arguments to those passed to the bound
3314
+ * function. This method differs from `_.bind` by allowing bound functions to
3315
+ * reference methods that will be redefined or don't yet exist.
3316
+ *
3317
+ * @static
3318
+ * @memberOf _
3319
+ * @category Functions
3320
+ * @param {Object} object The object the method belongs to.
3321
+ * @param {String} methodName The method name.
3322
+ * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
3323
+ * @returns {Function} Returns the new bound function.
3324
+ * @example
3325
+ *
3326
+ * var object = {
3327
+ * 'name': 'moe',
3328
+ * 'greet': function(greeting) {
3329
+ * return greeting + ' ' + this.name;
3330
+ * }
3331
+ * };
3332
+ *
3333
+ * var func = _.lateBind(object, 'greet', 'hi');
3334
+ * func();
3335
+ * // => 'hi moe'
3336
+ *
3337
+ * object.greet = function(greeting) {
3338
+ * return greeting + ', ' + this.name + '!';
3339
+ * };
3340
+ *
3341
+ * func();
3342
+ * // => 'hi, moe!'
3343
+ */
3344
+ function lateBind(object, methodName) {
3345
+ return createBound(methodName, object, slice.call(arguments, 2));
3346
+ }
3347
+
3348
+ /**
3349
+ * Creates a function that memoizes the result of `func`. If `resolver` is
3564
3350
  * passed, it will be used to determine the cache key for storing the result
3565
3351
  * based on the arguments passed to the memoized function. By default, the first
3566
3352
  * argument passed to the memoized function is used as the cache key.
@@ -3588,7 +3374,7 @@
3588
3374
  }
3589
3375
 
3590
3376
  /**
3591
- * Creates a new function that is restricted to one execution. Repeat calls to
3377
+ * Creates a function that is restricted to one execution. Repeat calls to
3592
3378
  * the function will return the value of the first call.
3593
3379
  *
3594
3380
  * @static
@@ -3621,9 +3407,9 @@
3621
3407
  }
3622
3408
 
3623
3409
  /**
3624
- * Creates a new function that, when called, invokes `func` with any additional
3410
+ * Creates a function that, when called, invokes `func` with any additional
3625
3411
  * `partial` arguments prepended to those passed to the new function. This method
3626
- * is similar `bind`, except it does **not** alter the `this` binding.
3412
+ * is similar to `bind`, except it does **not** alter the `this` binding.
3627
3413
  *
3628
3414
  * @static
3629
3415
  * @memberOf _
@@ -3639,25 +3425,11 @@
3639
3425
  * // => 'hi: moe'
3640
3426
  */
3641
3427
  function partial(func) {
3642
- var args = slice.call(arguments, 1),
3643
- argsLength = args.length;
3644
-
3645
- return function() {
3646
- var result,
3647
- others = arguments;
3648
-
3649
- if (others.length) {
3650
- args.length = argsLength;
3651
- push.apply(args, others);
3652
- }
3653
- result = args.length == 1 ? func.call(this, args[0]) : func.apply(this, args);
3654
- args.length = argsLength;
3655
- return result;
3656
- };
3428
+ return createBound(func, slice.call(arguments, 1));
3657
3429
  }
3658
3430
 
3659
3431
  /**
3660
- * Creates a new function that, when executed, will only call the `func`
3432
+ * Creates a function that, when executed, will only call the `func`
3661
3433
  * function at most once per every `wait` milliseconds. If the throttled
3662
3434
  * function is invoked more than once during the `wait` timeout, `func` will
3663
3435
  * also be called on the trailing edge of the timeout. Subsequent calls to the
@@ -3706,7 +3478,7 @@
3706
3478
  }
3707
3479
 
3708
3480
  /**
3709
- * Creates a new function that passes `value` to the `wrapper` function as its
3481
+ * Creates a function that passes `value` to the `wrapper` function as its
3710
3482
  * first argument. Additional arguments passed to the new function are appended
3711
3483
  * to those passed to the `wrapper` function.
3712
3484
  *
@@ -3801,14 +3573,14 @@
3801
3573
  forEach(functions(object), function(methodName) {
3802
3574
  var func = lodash[methodName] = object[methodName];
3803
3575
 
3804
- LoDash.prototype[methodName] = function() {
3576
+ lodash.prototype[methodName] = function() {
3805
3577
  var args = [this.__wrapped__];
3806
3578
  if (arguments.length) {
3807
3579
  push.apply(args, arguments);
3808
3580
  }
3809
3581
  var result = func.apply(lodash, args);
3810
3582
  if (this.__chain__) {
3811
- result = new LoDash(result);
3583
+ result = new lodash(result);
3812
3584
  result.__chain__ = true;
3813
3585
  }
3814
3586
  return result;
@@ -3836,13 +3608,12 @@
3836
3608
  /**
3837
3609
  * Produces a random number between `min` and `max` (inclusive). If only one
3838
3610
  * argument is passed, a number between `0` and the given number will be returned.
3839
- * If no arguments are passed `_.random` will act as `Math.random`.
3840
3611
  *
3841
3612
  * @static
3842
3613
  * @memberOf _
3843
3614
  * @category Utilities
3844
- * @param {Number} min The minimum possible value.
3845
- * @param {Number} max The maximum possible value.
3615
+ * @param {Number} [min=0] The minimum possible value.
3616
+ * @param {Number} [max=1] The maximum possible value.
3846
3617
  * @returns {Number} Returns a random number.
3847
3618
  * @example
3848
3619
  *
@@ -3851,13 +3622,10 @@
3851
3622
  *
3852
3623
  * _.random(5);
3853
3624
  * // => also a number between 1 and 5
3854
- *
3855
- * _.random();
3856
- * // => an integer between 0 and less than 1
3857
3625
  */
3858
3626
  function random(min, max) {
3859
3627
  if (min == null && max == null) {
3860
- return nativeRandom();
3628
+ max = 1;
3861
3629
  }
3862
3630
  min = +min || 0;
3863
3631
  if (max == null) {
@@ -3877,7 +3645,7 @@
3877
3645
  * @memberOf _
3878
3646
  * @category Utilities
3879
3647
  * @param {Object} object The object to inspect.
3880
- * @param {String} property The property to get the result of.
3648
+ * @param {String} property The property to get the value of.
3881
3649
  * @returns {Mixed} Returns the resolved value.
3882
3650
  * @example
3883
3651
  *
@@ -3897,10 +3665,7 @@
3897
3665
  function result(object, property) {
3898
3666
  // based on Backbone's private `getValue` function
3899
3667
  // https://github.com/documentcloud/backbone/blob/0.9.2/backbone.js#L1419-1424
3900
- if (!object) {
3901
- return null;
3902
- }
3903
- var value = object[property];
3668
+ var value = object ? object[property] : null;
3904
3669
  return isFunction(value) ? object[property]() : value;
3905
3670
  }
3906
3671
 
@@ -3930,7 +3695,7 @@
3930
3695
  * compiled({ 'name': 'moe' });
3931
3696
  * // => 'hello: moe'
3932
3697
  *
3933
- * var list = '<% _.forEach(people, function(name) { %> <li><%= name %></li> <% }); %>';
3698
+ * var list = '<% _.forEach(people, function(name) { %><li><%= name %></li><% }); %>';
3934
3699
  * _.template(list, { 'people': ['moe', 'larry', 'curly'] });
3935
3700
  * // => '<li>moe</li><li>larry</li><li>curly</li>'
3936
3701
  *
@@ -3939,12 +3704,12 @@
3939
3704
  * // => '<b>&lt;script></b>'
3940
3705
  *
3941
3706
  * // using the internal `print` function in "evaluate" delimiters
3942
- * _.template('<% print("Hello " + epithet); %>', { 'epithet': 'stooge' });
3707
+ * _.template('<% print("Hello " + epithet); %>.', { 'epithet': 'stooge' });
3943
3708
  * // => 'Hello stooge.'
3944
3709
  *
3945
3710
  * // using custom template delimiter settings
3946
3711
  * _.templateSettings = {
3947
- * 'interpolate': /\{\{(.+?)\}\}/g
3712
+ * 'interpolate': /\{\{([\s\S]+?)\}\}/g
3948
3713
  * };
3949
3714
  *
3950
3715
  * _.template('Hello {{ name }}!', { 'name': 'Mustache' });
@@ -3972,90 +3737,64 @@
3972
3737
  // http://ejohn.org/blog/javascript-micro-templating/
3973
3738
  // and Laura Doktorova's doT.js
3974
3739
  // https://github.com/olado/doT
3975
- options || (options = {});
3976
3740
  text += '';
3741
+ options || (options = {});
3977
3742
 
3978
3743
  var isEvaluating,
3979
3744
  result,
3980
- escapeDelimiter = options.escape,
3981
- evaluateDelimiter = options.evaluate,
3982
- interpolateDelimiter = options.interpolate,
3745
+ index = 0,
3983
3746
  settings = lodash.templateSettings,
3747
+ source = "__p += '",
3984
3748
  variable = options.variable || settings.variable,
3985
3749
  hasVariable = variable;
3986
3750
 
3987
- // use default settings if no options object is provided
3988
- if (escapeDelimiter == null) {
3989
- escapeDelimiter = settings.escape;
3990
- }
3991
- if (evaluateDelimiter == null) {
3992
- // use `false` as the fallback value, instead of leaving it `undefined`,
3993
- // so the initial assignment of `reEvaluateDelimiter` will still occur
3994
- evaluateDelimiter = settings.evaluate || false;
3995
- }
3996
- if (interpolateDelimiter == null) {
3997
- interpolateDelimiter = settings.interpolate;
3998
- }
3999
-
4000
- // tokenize delimiters to avoid escaping them
4001
- if (escapeDelimiter) {
4002
- text = text.replace(escapeDelimiter, tokenizeEscape);
4003
- }
4004
- if (interpolateDelimiter) {
4005
- text = text.replace(interpolateDelimiter, tokenizeInterpolate);
4006
- }
4007
- if (evaluateDelimiter != lastEvaluateDelimiter) {
4008
- // generate `reEvaluateDelimiter` to match `_.templateSettings.evaluate`
4009
- // and internal `<e%- %>`, `<e%= %>` delimiters
4010
- lastEvaluateDelimiter = evaluateDelimiter;
4011
- reEvaluateDelimiter = RegExp(
4012
- '<e%-([\\s\\S]+?)%>|<e%=([\\s\\S]+?)%>' +
4013
- (evaluateDelimiter ? '|' + evaluateDelimiter.source : '')
4014
- , 'g');
4015
- }
4016
- isEvaluating = tokenized.length;
4017
- text = text.replace(reEvaluateDelimiter, tokenizeEvaluate);
4018
- isEvaluating = isEvaluating != tokenized.length;
4019
-
4020
- // escape characters that cannot be included in string literals and
4021
- // detokenize delimiter code snippets
4022
- text = "__p += '" + text
4023
- .replace(reUnescapedString, escapeStringChar)
4024
- .replace(reToken, detokenize) + "';\n";
3751
+ // compile regexp to match each delimiter
3752
+ var reDelimiters = RegExp(
3753
+ (options.escape || settings.escape || reNoMatch).source + '|' +
3754
+ (options.interpolate || settings.interpolate || reNoMatch).source + '|' +
3755
+ (options.evaluate || settings.evaluate || reNoMatch).source + '|$'
3756
+ , 'g');
3757
+
3758
+ text.replace(reDelimiters, function(match, escapeValue, interpolateValue, evaluateValue, offset) {
3759
+ // escape characters that cannot be included in string literals
3760
+ source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);
3761
+
3762
+ // replace delimiters with snippets
3763
+ source +=
3764
+ escapeValue ? "' +\n__e(" + escapeValue + ") +\n'" :
3765
+ evaluateValue ? "';\n" + evaluateValue + ";\n__p += '" :
3766
+ interpolateValue ? "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'" : '';
3767
+
3768
+ isEvaluating || (isEvaluating = evaluateValue || reComplexDelimiter.test(escapeValue || interpolateValue));
3769
+ index = offset + match.length;
3770
+ });
4025
3771
 
4026
- // clear stored code snippets
4027
- tokenized.length = 0;
3772
+ source += "';\n";
4028
3773
 
4029
3774
  // if `variable` is not specified and the template contains "evaluate"
4030
3775
  // delimiters, wrap a with-statement around the generated code to add the
4031
3776
  // data object to the top of the scope chain
4032
3777
  if (!hasVariable) {
4033
- variable = lastVariable || 'obj';
4034
-
3778
+ variable = 'obj';
4035
3779
  if (isEvaluating) {
4036
- text = 'with (' + variable + ') {\n' + text + '\n}\n';
3780
+ source = 'with (' + variable + ') {\n' + source + '\n}\n';
4037
3781
  }
4038
3782
  else {
4039
- if (variable != lastVariable) {
4040
- // generate `reDoubleVariable` to match references like `obj.obj` inside
4041
- // transformed "escape" and "interpolate" delimiters
4042
- lastVariable = variable;
4043
- reDoubleVariable = RegExp('(\\(\\s*)' + variable + '\\.' + variable + '\\b', 'g');
4044
- }
4045
3783
  // avoid a with-statement by prepending data object references to property names
4046
- text = text
3784
+ var reDoubleVariable = RegExp('(\\(\\s*)' + variable + '\\.' + variable + '\\b', 'g');
3785
+ source = source
4047
3786
  .replace(reInsertVariable, '$&' + variable + '.')
4048
3787
  .replace(reDoubleVariable, '$1__d');
4049
3788
  }
4050
3789
  }
4051
3790
 
4052
3791
  // cleanup code by stripping empty strings
4053
- text = ( isEvaluating ? text.replace(reEmptyStringLeading, '') : text)
3792
+ source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
4054
3793
  .replace(reEmptyStringMiddle, '$1')
4055
3794
  .replace(reEmptyStringTrailing, '$1;');
4056
3795
 
4057
3796
  // frame code as the function body
4058
- text = 'function(' + variable + ') {\n' +
3797
+ source = 'function(' + variable + ') {\n' +
4059
3798
  (hasVariable ? '' : variable + ' || (' + variable + ' = {});\n') +
4060
3799
  'var __t, __p = \'\', __e = _.escape' +
4061
3800
  (isEvaluating
@@ -4063,19 +3802,19 @@
4063
3802
  'function print() { __p += __j.call(arguments, \'\') }\n'
4064
3803
  : (hasVariable ? '' : ', __d = ' + variable + '.' + variable + ' || ' + variable) + ';\n'
4065
3804
  ) +
4066
- text +
3805
+ source +
4067
3806
  'return __p\n}';
4068
3807
 
4069
- // add a sourceURL for easier debugging
3808
+ // use a sourceURL for easier debugging
4070
3809
  // http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
4071
- if (useSourceURL) {
4072
- text += '\n//@ sourceURL=/lodash/template/source[' + (templateCounter++) + ']';
4073
- }
3810
+ var sourceURL = useSourceURL
3811
+ ? '\n//@ sourceURL=/lodash/template/source[' + (templateCounter++) + ']'
3812
+ : '';
4074
3813
 
4075
3814
  try {
4076
- result = Function('_', 'return ' + text)(lodash);
3815
+ result = Function('_', 'return ' + source + sourceURL)(lodash);
4077
3816
  } catch(e) {
4078
- e.source = text;
3817
+ e.source = source;
4079
3818
  throw e;
4080
3819
  }
4081
3820
 
@@ -4085,39 +3824,42 @@
4085
3824
  // provide the compiled function's source via its `toString` method, in
4086
3825
  // supported environments, or the `source` property as a convenience for
4087
3826
  // inlining compiled templates during the build process
4088
- result.source = text;
3827
+ result.source = source;
4089
3828
  return result;
4090
3829
  }
4091
3830
 
4092
3831
  /**
4093
- * Executes the `callback` function `n` times. The `callback` is bound to
4094
- * `thisArg` and invoked with 1 argument; (index).
3832
+ * Executes the `callback` function `n` times, returning an array of the results
3833
+ * of each `callback` execution. The `callback` is bound to `thisArg` and invoked
3834
+ * with one argument; (index).
4095
3835
  *
4096
3836
  * @static
4097
3837
  * @memberOf _
4098
3838
  * @category Utilities
4099
3839
  * @param {Number} n The number of times to execute the callback.
4100
3840
  * @param {Function} callback The function called per iteration.
4101
- * @param {Mixed} [thisArg] The `this` binding for the callback.
3841
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
3842
+ * @returns {Array} Returns a new array of the results of each `callback` execution.
4102
3843
  * @example
4103
3844
  *
4104
- * _.times(3, function(n) { genie.grantWish(n); });
4105
- * // => calls `genie.grantWish(n)` three times, passing `n` of `0`, `1`, and `2` respectively
3845
+ * var diceRolls = _.times(3, _.partial(_.random, 1, 6));
3846
+ * // => [3, 6, 4]
4106
3847
  *
4107
- * _.times(3, function(n) { this.grantWish(n); }, genie);
4108
- * // => also calls `genie.grantWish(n)` three times
3848
+ * _.times(3, function(n) { mage.castSpell(n); });
3849
+ * // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively
3850
+ *
3851
+ * _.times(3, function(n) { this.cast(n); }, mage);
3852
+ * // => also calls `mage.castSpell(n)` three times
4109
3853
  */
4110
3854
  function times(n, callback, thisArg) {
4111
- var index = -1;
4112
- if (thisArg) {
4113
- while (++index < n) {
4114
- callback.call(thisArg, index);
4115
- }
4116
- } else {
4117
- while (++index < n) {
4118
- callback(index);
4119
- }
3855
+ n = +n || 0;
3856
+ var index = -1,
3857
+ result = Array(n);
3858
+
3859
+ while (++index < n) {
3860
+ result[index] = callback.call(thisArg, index);
4120
3861
  }
3862
+ return result;
4121
3863
  }
4122
3864
 
4123
3865
  /**
@@ -4183,7 +3925,7 @@
4183
3925
  * // => 'moe is 40'
4184
3926
  */
4185
3927
  function chain(value) {
4186
- value = new LoDash(value);
3928
+ value = new lodash(value);
4187
3929
  value.__chain__ = true;
4188
3930
  return value;
4189
3931
  }
@@ -4201,7 +3943,7 @@
4201
3943
  * @returns {Mixed} Returns `value`.
4202
3944
  * @example
4203
3945
  *
4204
- * _.chain([1,2,3,200])
3946
+ * _.chain([1, 2, 3, 200])
4205
3947
  * .filter(function(num) { return num % 2 == 0; })
4206
3948
  * .tap(alert)
4207
3949
  * .map(function(num) { return num * num })
@@ -4257,7 +3999,7 @@
4257
3999
  * @memberOf _
4258
4000
  * @type String
4259
4001
  */
4260
- lodash.VERSION = '0.7.0';
4002
+ lodash.VERSION = '0.8.1';
4261
4003
 
4262
4004
  // assign static methods
4263
4005
  lodash.after = after;
@@ -4306,12 +4048,14 @@
4306
4048
  lodash.isNull = isNull;
4307
4049
  lodash.isNumber = isNumber;
4308
4050
  lodash.isObject = isObject;
4051
+ lodash.isPlainObject = isPlainObject;
4309
4052
  lodash.isRegExp = isRegExp;
4310
4053
  lodash.isString = isString;
4311
4054
  lodash.isUndefined = isUndefined;
4312
4055
  lodash.keys = keys;
4313
4056
  lodash.last = last;
4314
4057
  lodash.lastIndexOf = lastIndexOf;
4058
+ lodash.lateBind = lateBind;
4315
4059
  lodash.map = map;
4316
4060
  lodash.max = max;
4317
4061
  lodash.memoize = memoize;
@@ -4377,22 +4121,19 @@
4377
4121
 
4378
4122
  /*--------------------------------------------------------------------------*/
4379
4123
 
4380
- // assign private `LoDash` constructor's prototype
4381
- LoDash.prototype = lodash.prototype;
4382
-
4383
- // add all static functions to `LoDash.prototype`
4124
+ // add all static functions to `lodash.prototype`
4384
4125
  mixin(lodash);
4385
4126
 
4386
- // add `LoDash.prototype.chain` after calling `mixin()` to avoid overwriting
4127
+ // add `lodash.prototype.chain` after calling `mixin()` to avoid overwriting
4387
4128
  // it with the wrapped `lodash.chain`
4388
- LoDash.prototype.chain = wrapperChain;
4389
- LoDash.prototype.value = wrapperValue;
4129
+ lodash.prototype.chain = wrapperChain;
4130
+ lodash.prototype.value = wrapperValue;
4390
4131
 
4391
4132
  // add all mutator Array functions to the wrapper.
4392
4133
  forEach(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
4393
4134
  var func = ArrayProto[methodName];
4394
4135
 
4395
- LoDash.prototype[methodName] = function() {
4136
+ lodash.prototype[methodName] = function() {
4396
4137
  var value = this.__wrapped__;
4397
4138
  func.apply(value, arguments);
4398
4139
 
@@ -4402,7 +4143,7 @@
4402
4143
  delete value[0];
4403
4144
  }
4404
4145
  if (this.__chain__) {
4405
- value = new LoDash(value);
4146
+ value = new lodash(value);
4406
4147
  value.__chain__ = true;
4407
4148
  }
4408
4149
  return value;
@@ -4413,12 +4154,12 @@
4413
4154
  forEach(['concat', 'join', 'slice'], function(methodName) {
4414
4155
  var func = ArrayProto[methodName];
4415
4156
 
4416
- LoDash.prototype[methodName] = function() {
4157
+ lodash.prototype[methodName] = function() {
4417
4158
  var value = this.__wrapped__,
4418
4159
  result = func.apply(value, arguments);
4419
4160
 
4420
4161
  if (this.__chain__) {
4421
- result = new LoDash(result);
4162
+ result = new lodash(result);
4422
4163
  result.__chain__ = true;
4423
4164
  }
4424
4165
  return result;