underscore-source 0.5.0 → 0.5.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 = "0.5.0"
3
+ VERSION = "0.5.1"
4
4
  end
5
5
  end
@@ -30,8 +30,15 @@
30
30
  // Export the Underscore object for CommonJS.
31
31
  if (typeof exports !== 'undefined') exports._ = _;
32
32
 
33
+ // Create quick reference variables for speed access to core prototypes.
34
+ var slice = Array.prototype.slice,
35
+ unshift = Array.prototype.unshift,
36
+ toString = Object.prototype.toString,
37
+ hasOwnProperty = Object.prototype.hasOwnProperty,
38
+ propertyIsEnumerable = Object.prototype.propertyIsEnumerable;
39
+
33
40
  // Current version.
34
- _.VERSION = '0.5.0';
41
+ _.VERSION = '0.5.1';
35
42
 
36
43
  /*------------------------ Collection Functions: ---------------------------*/
37
44
 
@@ -42,7 +49,7 @@
42
49
  try {
43
50
  if (obj.forEach) {
44
51
  obj.forEach(iterator, context);
45
- } else if (obj.length) {
52
+ } else if (_.isArray(obj) || _.isArguments(obj)) {
46
53
  for (var i=0, l=obj.length; i<l; i++) iterator.call(context, obj[i], i, obj);
47
54
  } else {
48
55
  var keys = _.keys(obj), l = keys.length;
@@ -57,7 +64,7 @@
57
64
  // Return the results of applying the iterator to each element. Use JavaScript
58
65
  // 1.6's version of map, if possible.
59
66
  _.map = function(obj, iterator, context) {
60
- if (obj && obj.map) return obj.map(iterator, context);
67
+ if (obj && _.isFunction(obj.map)) return obj.map(iterator, context);
61
68
  var results = [];
62
69
  _.each(obj, function(value, index, list) {
63
70
  results.push(iterator.call(context, value, index, list));
@@ -68,7 +75,7 @@
68
75
  // Reduce builds up a single result from a list of values. Also known as
69
76
  // inject, or foldl. Uses JavaScript 1.8's version of reduce, if possible.
70
77
  _.reduce = function(obj, memo, iterator, context) {
71
- if (obj && obj.reduce) return obj.reduce(_.bind(iterator, context), memo);
78
+ if (obj && _.isFunction(obj.reduce)) return obj.reduce(_.bind(iterator, context), memo);
72
79
  _.each(obj, function(value, index, list) {
73
80
  memo = iterator.call(context, memo, value, index, list);
74
81
  });
@@ -78,7 +85,7 @@
78
85
  // The right-associative version of reduce, also known as foldr. Uses
79
86
  // JavaScript 1.8's version of reduceRight, if available.
80
87
  _.reduceRight = function(obj, memo, iterator, context) {
81
- if (obj && obj.reduceRight) return obj.reduceRight(_.bind(iterator, context), memo);
88
+ if (obj && _.isFunction(obj.reduceRight)) return obj.reduceRight(_.bind(iterator, context), memo);
82
89
  var reversed = _.clone(_.toArray(obj)).reverse();
83
90
  _.each(reversed, function(value, index) {
84
91
  memo = iterator.call(context, memo, value, index, obj);
@@ -101,7 +108,7 @@
101
108
  // Return all the elements that pass a truth test. Use JavaScript 1.6's
102
109
  // filter(), if it exists.
103
110
  _.select = function(obj, iterator, context) {
104
- if (obj.filter) return obj.filter(iterator, context);
111
+ if (obj && _.isFunction(obj.filter)) return obj.filter(iterator, context);
105
112
  var results = [];
106
113
  _.each(obj, function(value, index, list) {
107
114
  iterator.call(context, value, index, list) && results.push(value);
@@ -122,7 +129,7 @@
122
129
  // JavaScript 1.6's every(), if it is present.
123
130
  _.all = function(obj, iterator, context) {
124
131
  iterator = iterator || _.identity;
125
- if (obj.every) return obj.every(iterator, context);
132
+ if (obj && _.isFunction(obj.every)) return obj.every(iterator, context);
126
133
  var result = true;
127
134
  _.each(obj, function(value, index, list) {
128
135
  if (!(result = result && iterator.call(context, value, index, list))) _.breakLoop();
@@ -134,7 +141,7 @@
134
141
  // JavaScript 1.6's some(), if it exists.
135
142
  _.any = function(obj, iterator, context) {
136
143
  iterator = iterator || _.identity;
137
- if (obj.some) return obj.some(iterator, context);
144
+ if (obj && _.isFunction(obj.some)) return obj.some(iterator, context);
138
145
  var result = false;
139
146
  _.each(obj, function(value, index, list) {
140
147
  if (result = iterator.call(context, value, index, list)) _.breakLoop();
@@ -215,9 +222,10 @@
215
222
 
216
223
  // Convert anything iterable into a real, live array.
217
224
  _.toArray = function(iterable) {
218
- if (!iterable) return [];
219
- if (iterable.toArray) return iterable.toArray();
220
- if (_.isArray(iterable)) return iterable;
225
+ if (!iterable) return [];
226
+ if (iterable.toArray) return iterable.toArray();
227
+ if (_.isArray(iterable)) return iterable;
228
+ if (_.isArguments(iterable)) return slice.call(iterable);
221
229
  return _.map(iterable, function(val){ return val; });
222
230
  };
223
231
 
@@ -229,16 +237,18 @@
229
237
  /*-------------------------- Array Functions: ------------------------------*/
230
238
 
231
239
  // Get the first element of an array. Passing "n" will return the first N
232
- // values in the array. Aliased as "head".
233
- _.first = function(array, n) {
234
- return n ? Array.prototype.slice.call(array, 0, n) : array[0];
240
+ // values in the array. Aliased as "head". The "guard" check allows it to work
241
+ // with _.map.
242
+ _.first = function(array, n, guard) {
243
+ return n && !guard ? slice.call(array, 0, n) : array[0];
235
244
  };
236
245
 
237
246
  // Returns everything but the first entry of the array. Aliased as "tail".
238
247
  // Especially useful on the arguments object. Passing an "index" will return
239
- // the rest of the values in the array from that index onward.
240
- _.rest = function(array, index) {
241
- return Array.prototype.slice.call(array, _.isUndefined(index) ? 1 : index);
248
+ // the rest of the values in the array from that index onward. The "guard"
249
+ //check allows it to work with _.map.
250
+ _.rest = function(array, index, guard) {
251
+ return slice.call(array, _.isUndefined(index) || guard ? 1 : index);
242
252
  };
243
253
 
244
254
  // Get the last element of an array.
@@ -270,7 +280,7 @@
270
280
  // been sorted, you have the option of using a faster algorithm.
271
281
  _.uniq = function(array, isSorted) {
272
282
  return _.reduce(array, [], function(memo, el, i) {
273
- if (0 == i || (isSorted ? _.last(memo) != el : !_.include(memo, el))) memo.push(el);
283
+ if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) memo.push(el);
274
284
  return memo;
275
285
  });
276
286
  };
@@ -392,7 +402,7 @@
392
402
  _.keys = function(obj) {
393
403
  if(_.isArray(obj)) return _.range(0, obj.length);
394
404
  var keys = [];
395
- for (var key in obj) if (Object.prototype.hasOwnProperty.call(obj, key)) keys.push(key);
405
+ for (var key in obj) if (hasOwnProperty.call(obj, key)) keys.push(key);
396
406
  return keys;
397
407
  };
398
408
 
@@ -401,6 +411,11 @@
401
411
  return _.map(obj, _.identity);
402
412
  };
403
413
 
414
+ // Return a sorted list of the function names available in Underscore.
415
+ _.functions = function(obj) {
416
+ return _.select(_.keys(obj), function(key){ return _.isFunction(obj[key]); }).sort();
417
+ };
418
+
404
419
  // Extend a given object with all of the properties in a source object.
405
420
  _.extend = function(destination, source) {
406
421
  for (var property in source) destination[property] = source[property];
@@ -422,6 +437,8 @@
422
437
  if (atype != btype) return false;
423
438
  // Basic equality test (watch out for coercions).
424
439
  if (a == b) return true;
440
+ // One is falsy and the other truthy.
441
+ if ((!a && b) || (a && !b)) return false;
425
442
  // One of them implements an isEqual()?
426
443
  if (a.isEqual) return a.isEqual(b);
427
444
  // Check dates' integer values.
@@ -457,6 +474,11 @@
457
474
  return !!(obj && obj.nodeType == 1);
458
475
  };
459
476
 
477
+ // Is a given variable an arguments object?
478
+ _.isArguments = function(obj) {
479
+ return obj && _.isNumber(obj.length) && !_.isArray(obj) && !propertyIsEnumerable.call(obj, 'length');
480
+ };
481
+
460
482
  // Is the given value NaN -- this one is interesting. NaN != NaN, and
461
483
  // isNaN(undefined) == true, so we make sure it's a number first.
462
484
  _.isNaN = function(obj) {
@@ -473,13 +495,15 @@
473
495
  return typeof obj == 'undefined';
474
496
  };
475
497
 
476
- // Define the isArray, isDate, isFunction, isNumber, isRegExp, and
477
- // isString functions based on their toString identifiers.
478
- _.each(['Array', 'Date', 'Function', 'Number', 'RegExp', 'String'], function(type) {
479
- _['is' + type] = function(obj) {
480
- return Object.prototype.toString.call(obj) == '[object ' + type + ']';
481
- };
482
- });
498
+ // Define the isArray, isDate, isFunction, isNumber, isRegExp, and isString
499
+ // functions based on their toString identifiers.
500
+ var types = ['Array', 'Date', 'Function', 'Number', 'RegExp', 'String'];
501
+ for (var i=0, l=types.length; i<l; i++) {
502
+ (function() {
503
+ var identifier = '[object ' + types[i] + ']';
504
+ _['is' + types[i]] = function(obj) { return toString.call(obj) == identifier; };
505
+ })();
506
+ }
483
507
 
484
508
  /* -------------------------- Utility Functions: -------------------------- */
485
509
 
@@ -508,11 +532,6 @@
508
532
  return prefix ? prefix + id : id;
509
533
  };
510
534
 
511
- // Return a sorted list of the function names available in Underscore.
512
- _.functions = function(obj) {
513
- return _.select(_.keys(obj), function(key){ return _.isFunction(obj[key]); }).sort();
514
- };
515
-
516
535
  // JavaScript templating a-la ERB, pilfered from John Resig's
517
536
  // "Secrets of the JavaScript Ninja", page 83.
518
537
  _.template = function(str, data) {
@@ -552,24 +571,27 @@
552
571
 
553
572
  // Add all of the Underscore functions to the wrapper object.
554
573
  _.each(_.functions(_), function(name) {
574
+ var method = _[name];
555
575
  wrapper.prototype[name] = function() {
556
- Array.prototype.unshift.call(arguments, this._wrapped);
557
- return result(_[name].apply(_, arguments), this._chain);
576
+ unshift.call(arguments, this._wrapped);
577
+ return result(method.apply(_, arguments), this._chain);
558
578
  };
559
579
  });
560
580
 
561
581
  // Add all mutator Array functions to the wrapper.
562
582
  _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
583
+ var method = Array.prototype[name];
563
584
  wrapper.prototype[name] = function() {
564
- Array.prototype[name].apply(this._wrapped, arguments);
585
+ method.apply(this._wrapped, arguments);
565
586
  return result(this._wrapped, this._chain);
566
587
  };
567
588
  });
568
589
 
569
590
  // Add all accessor Array functions to the wrapper.
570
591
  _.each(['concat', 'join', 'slice'], function(name) {
592
+ var method = Array.prototype[name];
571
593
  wrapper.prototype[name] = function() {
572
- return result(Array.prototype[name].apply(this._wrapped, arguments), this._chain);
594
+ return result(method.apply(this._wrapped, arguments), this._chain);
573
595
  };
574
596
  });
575
597
 
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: underscore-source
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.5.0
5
+ version: 0.5.1
6
6
  platform: ruby
7
7
  authors:
8
8
  - Daniel X. Moore