underscore-source 1.2.0 → 1.2.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.
@@ -1,5 +1,5 @@
1
1
  module Underscore
2
2
  module Source
3
- VERSION = "1.2.0"
3
+ VERSION = "1.2.1"
4
4
  end
5
5
  end
@@ -1,4 +1,4 @@
1
- // Underscore.js 1.2.0
1
+ // Underscore.js 1.2.1
2
2
  // (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.
3
3
  // Underscore is freely distributable under the MIT license.
4
4
  // Portions of Underscore are inspired or borrowed from Prototype,
@@ -48,19 +48,26 @@
48
48
  // Create a safe reference to the Underscore object for use below.
49
49
  var _ = function(obj) { return new wrapper(obj); };
50
50
 
51
- // Export the Underscore object for **CommonJS**, with backwards-compatibility
52
- // for the old `require()` API. If we're not in CommonJS, add `_` to the
53
- // global object.
54
- if (typeof module !== 'undefined' && module.exports) {
55
- module.exports = _;
56
- _._ = _;
51
+ // Export the Underscore object for **Node.js** and **"CommonJS"**, with
52
+ // backwards-compatibility for the old `require()` API. If we're not in
53
+ // CommonJS, add `_` to the global object.
54
+ if (typeof exports !== 'undefined') {
55
+ if (typeof module !== 'undefined' && module.exports) {
56
+ exports = module.exports = _;
57
+ }
58
+ exports._ = _;
59
+ } else if (typeof define === 'function' && define.amd) {
60
+ // Register as a named module with AMD.
61
+ define('underscore', function() {
62
+ return _;
63
+ });
57
64
  } else {
58
65
  // Exported as a string, for Closure Compiler "advanced" mode.
59
66
  root['_'] = _;
60
67
  }
61
68
 
62
69
  // Current version.
63
- _.VERSION = '1.2.0';
70
+ _.VERSION = '1.2.1';
64
71
 
65
72
  // Collection Functions
66
73
  // --------------------
@@ -198,8 +205,8 @@
198
205
  var found = false;
199
206
  if (obj == null) return found;
200
207
  if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
201
- any(obj, function(value) {
202
- if (found = value === target) return true;
208
+ found = any(obj, function(value) {
209
+ if (value === target) return true;
203
210
  });
204
211
  return found;
205
212
  };
@@ -269,9 +276,11 @@
269
276
  }), 'value');
270
277
  };
271
278
 
272
- // Groups the object's values by a criterion produced by an iterator
273
- _.groupBy = function(obj, iterator) {
279
+ // Groups the object's values by a criterion. Pass either a string attribute
280
+ // to group by, or a function that returns the criterion.
281
+ _.groupBy = function(obj, val) {
274
282
  var result = {};
283
+ var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
275
284
  each(obj, function(value, index) {
276
285
  var key = iterator(value, index);
277
286
  (result[key] || (result[key] = [])).push(value);
@@ -343,9 +352,9 @@
343
352
  };
344
353
 
345
354
  // Return a completely flattened version of an array.
346
- _.flatten = function(array) {
355
+ _.flatten = function(array, shallow) {
347
356
  return _.reduce(array, function(memo, value) {
348
- if (_.isArray(value)) return memo.concat(_.flatten(value));
357
+ if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value));
349
358
  memo[memo.length] = value;
350
359
  return memo;
351
360
  }, []);
@@ -375,7 +384,7 @@
375
384
  // Produce an array that contains the union: each distinct element from all of
376
385
  // the passed-in arrays.
377
386
  _.union = function() {
378
- return _.uniq(_.flatten(arguments));
387
+ return _.uniq(_.flatten(arguments, true));
379
388
  };
380
389
 
381
390
  // Produce an array that contains every item shared between all the
@@ -457,15 +466,25 @@
457
466
  // Function (ahem) Functions
458
467
  // ------------------
459
468
 
469
+ // Reusable constructor function for prototype setting.
470
+ var ctor = function(){};
471
+
460
472
  // Create a function bound to a given object (assigning `this`, and arguments,
461
473
  // optionally). Binding with arguments is also known as `curry`.
462
474
  // Delegates to **ECMAScript 5**'s native `Function.bind` if available.
463
475
  // We check for `func.bind` first, to fail fast when `func` is undefined.
464
- _.bind = function(func, obj) {
476
+ _.bind = function bind(func, context) {
477
+ var bound, args;
465
478
  if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
466
- var args = slice.call(arguments, 2);
467
- return function() {
468
- return func.apply(obj, args.concat(slice.call(arguments)));
479
+ if (!_.isFunction(func)) throw new TypeError;
480
+ args = slice.call(arguments, 2);
481
+ return bound = function() {
482
+ if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
483
+ ctor.prototype = func.prototype;
484
+ var self = new ctor;
485
+ var result = func.apply(self, args.concat(slice.call(arguments)));
486
+ if (Object(result) === result) return result;
487
+ return self;
469
488
  };
470
489
  };
471
490
 
@@ -501,31 +520,39 @@
501
520
  return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
502
521
  };
503
522
 
504
- // Internal function used to implement `_.throttle` and `_.debounce`.
505
- var limit = function(func, wait, debounce) {
506
- var timeout;
523
+ // Returns a function, that, when invoked, will only be triggered at most once
524
+ // during a given window of time.
525
+ _.throttle = function(func, wait) {
526
+ var timeout, context, args, throttling, finishThrottle;
527
+ finishThrottle = _.debounce(function(){ throttling = false; }, wait);
507
528
  return function() {
508
- var context = this, args = arguments;
529
+ context = this; args = arguments;
509
530
  var throttler = function() {
510
531
  timeout = null;
511
532
  func.apply(context, args);
533
+ finishThrottle();
512
534
  };
513
- if (debounce) clearTimeout(timeout);
514
- if (debounce || !timeout) timeout = setTimeout(throttler, wait);
535
+ if (!timeout) timeout = setTimeout(throttler, wait);
536
+ if (!throttling) func.apply(context, args);
537
+ if (finishThrottle) finishThrottle();
538
+ throttling = true;
515
539
  };
516
540
  };
517
541
 
518
- // Returns a function, that, when invoked, will only be triggered at most once
519
- // during a given window of time.
520
- _.throttle = function(func, wait) {
521
- return limit(func, wait, false);
522
- };
523
-
524
542
  // Returns a function, that, as long as it continues to be invoked, will not
525
543
  // be triggered. The function will be called after it stops being called for
526
544
  // N milliseconds.
527
545
  _.debounce = function(func, wait) {
528
- return limit(func, wait, true);
546
+ var timeout;
547
+ return function() {
548
+ var context = this, args = arguments;
549
+ var throttler = function() {
550
+ timeout = null;
551
+ func.apply(context, args);
552
+ };
553
+ clearTimeout(timeout);
554
+ timeout = setTimeout(throttler, wait);
555
+ };
529
556
  };
530
557
 
531
558
  // Returns a function that will be executed at most one time, no matter how
@@ -618,6 +645,7 @@
618
645
 
619
646
  // Create a (shallow-cloned) duplicate of an object.
620
647
  _.clone = function(obj) {
648
+ if (!_.isObject(obj)) return obj;
621
649
  return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
622
650
  };
623
651
 
@@ -635,7 +663,13 @@
635
663
  // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
636
664
  if (a === b) return a !== 0 || 1 / a == 1 / b;
637
665
  // A strict comparison is necessary because `null == undefined`.
638
- if (a == null) return a === b;
666
+ if ((a == null) || (b == null)) return a === b;
667
+ // Unwrap any wrapped objects.
668
+ if (a._chain) a = a._wrapped;
669
+ if (b._chain) b = b._wrapped;
670
+ // Invoke a custom `isEqual` method if one is provided.
671
+ if (_.isFunction(a.isEqual)) return a.isEqual(b);
672
+ if (_.isFunction(b.isEqual)) return b.isEqual(a);
639
673
  // Compare object types.
640
674
  var typeA = typeof a;
641
675
  if (typeA != typeof b) return false;
@@ -667,50 +701,36 @@
667
701
  }
668
702
  // Ensure that both values are objects.
669
703
  if (typeA != 'object') return false;
670
- // Unwrap any wrapped objects.
671
- if (a._chain) a = a._wrapped;
672
- if (b._chain) b = b._wrapped;
673
- // Invoke a custom `isEqual` method if one is provided.
674
- if (_.isFunction(a.isEqual)) return a.isEqual(b);
675
- // Assume equality for cyclic structures. The algorithm for detecting cyclic structures is
676
- // adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
704
+ // Arrays or Arraylikes with different lengths are not equal.
705
+ if (a.length !== b.length) return false;
706
+ // Objects with different constructors are not equal.
707
+ if (a.constructor !== b.constructor) return false;
708
+ // Assume equality for cyclic structures. The algorithm for detecting cyclic
709
+ // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
677
710
  var length = stack.length;
678
711
  while (length--) {
679
- // Linear search. Performance is inversely proportional to the number of unique nested
680
- // structures.
712
+ // Linear search. Performance is inversely proportional to the number of
713
+ // unique nested structures.
681
714
  if (stack[length] == a) return true;
682
715
  }
683
716
  // Add the first object to the stack of traversed objects.
684
717
  stack.push(a);
685
718
  var size = 0, result = true;
686
- if (a.length === +a.length || b.length === +b.length) {
687
- // Compare object lengths to determine if a deep comparison is necessary.
688
- size = a.length;
689
- result = size == b.length;
690
- if (result) {
691
- // Deep compare array-like object contents, ignoring non-numeric properties.
692
- while (size--) {
693
- // Ensure commutative equality for sparse arrays.
694
- if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break;
695
- }
696
- }
697
- } else {
698
- // Deep compare objects.
699
- for (var key in a) {
700
- if (hasOwnProperty.call(a, key)) {
701
- // Count the expected number of properties.
702
- size++;
703
- // Deep compare each member.
704
- if (!(result = hasOwnProperty.call(b, key) && eq(a[key], b[key], stack))) break;
705
- }
719
+ // Deep compare objects.
720
+ for (var key in a) {
721
+ if (hasOwnProperty.call(a, key)) {
722
+ // Count the expected number of properties.
723
+ size++;
724
+ // Deep compare each member.
725
+ if (!(result = hasOwnProperty.call(b, key) && eq(a[key], b[key], stack))) break;
706
726
  }
707
- // Ensure that both objects contain the same number of properties.
708
- if (result) {
709
- for (key in b) {
710
- if (hasOwnProperty.call(b, key) && !size--) break;
711
- }
712
- result = !size;
727
+ }
728
+ // Ensure that both objects contain the same number of properties.
729
+ if (result) {
730
+ for (key in b) {
731
+ if (hasOwnProperty.call(b, key) && !size--) break;
713
732
  }
733
+ result = !size;
714
734
  }
715
735
  // Remove the first object from the stack of traversed objects.
716
736
  stack.pop();
@@ -722,7 +742,8 @@
722
742
  return eq(a, b, []);
723
743
  };
724
744
 
725
- // Is a given array or object empty?
745
+ // Is a given array, string, or object empty?
746
+ // An "empty" object has no enumerable own-properties.
726
747
  _.isEmpty = function(obj) {
727
748
  if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
728
749
  for (var key in obj) if (hasOwnProperty.call(obj, key)) return false;
@@ -737,7 +758,7 @@
737
758
  // Is a given value an array?
738
759
  // Delegates to ECMA5's native Array.isArray
739
760
  _.isArray = nativeIsArray || function(obj) {
740
- return toString.call(obj) === '[object Array]';
761
+ return toString.call(obj) == '[object Array]';
741
762
  };
742
763
 
743
764
  // Is a given variable an object?
@@ -746,28 +767,34 @@
746
767
  };
747
768
 
748
769
  // Is a given variable an arguments object?
749
- _.isArguments = function(obj) {
750
- return !!(obj && hasOwnProperty.call(obj, 'callee'));
751
- };
770
+ if (toString.call(arguments) == '[object Arguments]') {
771
+ _.isArguments = function(obj) {
772
+ return toString.call(obj) == '[object Arguments]';
773
+ };
774
+ } else {
775
+ _.isArguments = function(obj) {
776
+ return !!(obj && hasOwnProperty.call(obj, 'callee'));
777
+ };
778
+ }
752
779
 
753
780
  // Is a given value a function?
754
781
  _.isFunction = function(obj) {
755
- return !!(obj && obj.constructor && obj.call && obj.apply);
782
+ return toString.call(obj) == '[object Function]';
756
783
  };
757
784
 
758
785
  // Is a given value a string?
759
786
  _.isString = function(obj) {
760
- return !!(obj === '' || (obj && obj.charCodeAt && obj.substr));
787
+ return toString.call(obj) == '[object String]';
761
788
  };
762
789
 
763
790
  // Is a given value a number?
764
791
  _.isNumber = function(obj) {
765
- return !!(obj === 0 || (obj && obj.toExponential && obj.toFixed));
792
+ return toString.call(obj) == '[object Number]';
766
793
  };
767
794
 
768
- // Is the given value `NaN`? `NaN` happens to be the only value in JavaScript
769
- // that does not equal itself.
795
+ // Is the given value `NaN`?
770
796
  _.isNaN = function(obj) {
797
+ // `NaN` is the only value for which `===` is not reflexive.
771
798
  return obj !== obj;
772
799
  };
773
800
 
@@ -778,12 +805,12 @@
778
805
 
779
806
  // Is a given value a date?
780
807
  _.isDate = function(obj) {
781
- return !!(obj && obj.getTimezoneOffset && obj.setUTCFullYear);
808
+ return toString.call(obj) == '[object Date]';
782
809
  };
783
810
 
784
811
  // Is the given value a regular expression?
785
812
  _.isRegExp = function(obj) {
786
- return !!(obj && obj.test && obj.exec && (obj.ignoreCase || obj.ignoreCase === false));
813
+ return toString.call(obj) == '[object RegExp]';
787
814
  };
788
815
 
789
816
  // Is a given value equal to null?
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: underscore-source
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 1.2.0
5
+ version: 1.2.1
6
6
  platform: ruby
7
7
  authors:
8
8
  - Daniel X. Moore