From 0513f60b63f08636dc0908730c7d4334aa322773 Mon Sep 17 00:00:00 2001 From: Tony Lukasavage Date: Tue, 18 Oct 2011 11:50:46 -0300 Subject: [PATCH 1/5] add support for CommonJS implementations that do not support modules.exports. --- underscore.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/underscore.js b/underscore.js index d19e26960..f09221580 100644 --- a/underscore.js +++ b/underscore.js @@ -54,6 +54,8 @@ if (typeof module !== 'undefined' && module.exports) { module.exports = _; _._ = _; + } else if (exports !== 'undefined') { + exports._ = _; } else { // Exported as a string, for Closure Compiler "advanced" mode. root['_'] = _; From 1054e24c4fe417f98adc3caeb8ec9cce7b39cdd1 Mon Sep 17 00:00:00 2001 From: Tony Lukasavage Date: Tue, 18 Oct 2011 13:27:18 -0300 Subject: [PATCH 2/5] made the exports check safe --- underscore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/underscore.js b/underscore.js index f09221580..47a330b06 100644 --- a/underscore.js +++ b/underscore.js @@ -54,7 +54,7 @@ if (typeof module !== 'undefined' && module.exports) { module.exports = _; _._ = _; - } else if (exports !== 'undefined') { + } else if (typeof exports !== 'undefined' && exports) { exports._ = _; } else { // Exported as a string, for Closure Compiler "advanced" mode. From 6123870dabb2b1ff8dc52be66c76de0248d78ddc Mon Sep 17 00:00:00 2001 From: Jeremy Ashkenas Date: Tue, 18 Oct 2011 15:02:06 -0400 Subject: [PATCH 3/5] Fixes #336 ... adds find alias for detect, and reorders to make the ES5 versions canonical. --- index.html | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/index.html b/index.html index 5faace35f..3353f7d0f 100644 --- a/index.html +++ b/index.html @@ -144,7 +144,7 @@
each, map, reduce, reduceRight, - detect, select, + find, filter, reject, all, any, include, invoke, pluck, @@ -312,8 +312,9 @@ var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []); => [4, 5, 2, 3, 0, 1] -

- detect_.detect(list, iterator, [context]) +

+ find_.find(list, iterator, [context]) + Alias: detect
Looks through each value in the list, returning the first one that passes a truth test (iterator). The function returns as @@ -321,20 +322,20 @@ var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []); entire list.

-var even = _.detect([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
+var even = _.find([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
 => 2
 
-

- select_.select(list, iterator, [context]) - Alias: filter +

+ filter_.filter(list, iterator, [context]) + Alias: select
Looks through each value in the list, returning an array of all the values that pass a truth test (iterator). Delegates to the native filter method, if it exists.

-var evens = _.select([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
+var evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
 => [2, 4, 6]
 
@@ -342,7 +343,7 @@ var evens = _.select([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; }); reject_.reject(list, iterator, [context])
Returns the values in list without the elements that the truth - test (iterator) passes. The opposite of select. + test (iterator) passes. The opposite of filter.

 var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
@@ -951,7 +952,7 @@ _.clone({name : 'moe'});
       

 _([1,2,3,200]).chain().
-  select(function(num) { return num % 2 == 0; }).
+  filter(function(num) { return num % 2 == 0; }).
   tap(console.log).
   map(function(num) { return num * num }).
   value();

From e79586515c5f635650afc32976826e01463dcd1d Mon Sep 17 00:00:00 2001
From: Jeremy Ashkenas 
Date: Tue, 18 Oct 2011 16:07:23 -0400
Subject: [PATCH 4/5] Issue #329 -- significant change to _.isEqual semantics.

---
 test/objects.js | 12 ++++++------
 underscore.js   | 41 +++++++++++++++--------------------------
 2 files changed, 21 insertions(+), 32 deletions(-)

diff --git a/test/objects.js b/test/objects.js
index c131d920b..5fc4b6a0a 100644
--- a/test/objects.js
+++ b/test/objects.js
@@ -154,8 +154,8 @@ $(document).ready(function() {
     ok(_.isEqual({}, {}), "Empty object literals are equal");
     ok(_.isEqual([], []), "Empty array literals are equal");
     ok(_.isEqual([{}], [{}]), "Empty nested arrays and objects are equal");
-    ok(_.isEqual({length: 0}, []), "Array-like objects and arrays are equal");
-    ok(_.isEqual([], {length: 0}), "Commutative equality is implemented for array-like objects");
+    ok(!_.isEqual({length: 0}, []), "Array-like objects and arrays are not equal.");
+    ok(!_.isEqual([], {length: 0}), "Commutative equality is implemented for array-like objects");
 
     ok(!_.isEqual({}, []), "Object literals and array literals are not equal");
     ok(!_.isEqual([], {}), "Commutative equality is implemented for objects and arrays");
@@ -174,7 +174,7 @@ $(document).ready(function() {
     b.join = b.pop = b.reverse = b.shift = b.slice = b.splice = b.concat = b.sort = b.unshift = null;
 
     // Array elements and properties.
-    ok(_.isEqual(a, b), "Arrays containing equivalent elements and different non-numeric properties are equal");
+    ok(!_.isEqual(a, b), "Arrays containing equivalent elements and different non-numeric properties are not equal");
     a.push("White Rocks");
     ok(!_.isEqual(a, b), "Arrays of different lengths are not equal");
     a.push("East Boulder");
@@ -183,7 +183,7 @@ $(document).ready(function() {
 
     // Sparse arrays.
     ok(_.isEqual(Array(3), Array(3)), "Sparse arrays of identical lengths are equal");
-    ok(!_.isEqual(Array(3), Array(6)), "Sparse arrays of different lengths are not equal");
+    ok(_.isEqual(Array(3), Array(6)), "Sparse arrays of different lengths are equal when both are empty");
 
     // According to the Microsoft deviations spec, section 2.1.26, JScript 5.x treats `undefined`
     // elements in arrays as elisions. Thus, sparse arrays and dense arrays containing `undefined`
@@ -235,8 +235,8 @@ $(document).ready(function() {
 
     // Instances.
     ok(_.isEqual(new First, new First), "Object instances are equal");
-    ok(_.isEqual(new First, new Second), "Objects with different constructors and identical own properties are equal");
-    ok(_.isEqual({value: 1}, new First), "Object instances and objects sharing equivalent properties are identical");
+    ok(!_.isEqual(new First, new Second), "Objects with different constructors and identical own properties are not equal");
+    ok(!_.isEqual({value: 1}, new First), "Object instances and objects sharing equivalent properties are not identical");
     ok(!_.isEqual({value: 2}, new Second), "The prototype chain of objects should not be examined");
 
     // Circular Arrays.
diff --git a/underscore.js b/underscore.js
index d19e26960..5e9d4f3e2 100644
--- a/underscore.js
+++ b/underscore.js
@@ -673,6 +673,8 @@
     }
     // Ensure that both values are objects.
     if (typeA != 'object') return false;
+    // Objects with different constructors are not equal.
+    if (a.constructor !== b.constructor) return false;
     // Assume equality for cyclic structures. The algorithm for detecting cyclic structures is
     // adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
     var length = stack.length;
@@ -684,34 +686,21 @@
     // Add the first object to the stack of traversed objects.
     stack.push(a);
     var size = 0, result = true;
-    if (a.length === +a.length || b.length === +b.length) {
-      // Compare object lengths to determine if a deep comparison is necessary.
-      size = a.length;
-      result = size == b.length;
-      if (result) {
-        // Deep compare array-like object contents, ignoring non-numeric properties.
-        while (size--) {
-          // Ensure commutative equality for sparse arrays.
-          if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break;
-        }
+    // Deep compare objects.
+    for (var key in a) {
+      if (hasOwnProperty.call(a, key)) {
+        // Count the expected number of properties.
+        size++;
+        // Deep compare each member.
+        if (!(result = hasOwnProperty.call(b, key) && eq(a[key], b[key], stack))) break;
       }
-    } else {
-      // Deep compare objects.
-      for (var key in a) {
-        if (hasOwnProperty.call(a, key)) {
-          // Count the expected number of properties.
-          size++;
-          // Deep compare each member.
-          if (!(result = hasOwnProperty.call(b, key) && eq(a[key], b[key], stack))) break;
-        }
-      }
-      // Ensure that both objects contain the same number of properties.
-      if (result) {
-        for (key in b) {
-          if (hasOwnProperty.call(b, key) && !size--) break;
-        }
-        result = !size;
+    }
+    // Ensure that both objects contain the same number of properties.
+    if (result) {
+      for (key in b) {
+        if (hasOwnProperty.call(b, key) && !size--) break;
       }
+      result = !size;
     }
     // Remove the first object from the stack of traversed objects.
     stack.pop();

From 86eedd2a7b2d02c282ce130c508b0c4f4e494789 Mon Sep 17 00:00:00 2001
From: Jeremy Ashkenas 
Date: Tue, 18 Oct 2011 16:51:45 -0400
Subject: [PATCH 5/5] Fixes #335, exporting for Titanium.

---
 underscore.js | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/underscore.js b/underscore.js
index 84c966ce3..1cb07d815 100644
--- a/underscore.js
+++ b/underscore.js
@@ -48,13 +48,13 @@
   // Create a safe reference to the Underscore object for use below.
   var _ = function(obj) { return new wrapper(obj); };
 
-  // Export the Underscore object for **CommonJS**, with backwards-compatibility
-  // for the old `require()` API. If we're not in CommonJS, add `_` to the
-  // global object.
-  if (typeof module !== 'undefined' && module.exports) {
-    module.exports = _;
-    _._ = _;
-  } else if (typeof exports !== 'undefined' && exports) {
+  // Export the Underscore object for **Node.js** and **"CommonJS"**, with
+  // backwards-compatibility for the old `require()` API. If we're not in
+  // CommonJS, add `_` to the global object.
+  if (typeof exports !== 'undefined') {
+    if (typeof module !== 'undefined' && module.exports) {
+      exports = module.exports = _;
+    }
     exports._ = _;
   } else {
     // Exported as a string, for Closure Compiler "advanced" mode.