lodash-rails 0.7.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -18,6 +18,6 @@ Add the necessary library to `app/assets/javascripts/application.js`:
18
18
 
19
19
  ## What's included?
20
20
 
21
- * Lo-Dash 0.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;