_.isEqual Implementations

Benchmark created by Kit Cambridge on


Preparation HTML

<!-- Latest version of Underscore on `master` -->
<script src="https://raw.github.com/documentcloud/underscore/master/underscore.js"></script>
<script>
var _master = _.noConflict();
</script>
<!-- Proposed in #351 -->
<script src="https://raw.github.com/kitcambridge/underscore/eq/underscore.js"></script>
<script>
var _351 = _.noConflict();
</script>

Setup

var _351 = window._351,
        _master = window._master;
    
    function ok(value){
      if (!value) throw new Error("Faulty result.");
    }
    
    function First() {
      this.value = 1;
    }
    First.prototype.value = 1;
    
    function Second() {
      this.value = 1;
    }
    Second.prototype.value = 2;

Test runner

Ready to run.

Testing in
TestOps/sec
master Implementation
// Basic equality and identity comparisons.
ok(_master.isEqual(null, null), "`null` is equal to `null`");
ok(_master.isEqual(), "`undefined` is equal to `undefined`");

ok(!_master.isEqual(0, -0), "`0` is not equal to `-0`");
ok(!_master.isEqual(-0, 0), "Commutative equality is implemented for `0` and `-0`");
ok(!_master.isEqual(null, undefined), "`null` is not equal to `undefined`");
ok(!_master.isEqual(undefined, null), "Commutative equality is implemented for `null` and `undefined`");

// String object and primitive comparisons.
ok(_master.isEqual("Curly", "Curly"), "Identical string primitives are equal");
ok(_master.isEqual(new String("Curly"), new String("Curly")), "String objects with identical primitive values are equal");

ok(!_master.isEqual("Curly", "Larry"), "String primitives with different values are not equal");
ok(!_master.isEqual(new String("Curly"), "Curly"), "String primitives and their corresponding object wrappers are not equal");
ok(!_master.isEqual("Curly", new String("Curly")), "Commutative equality is implemented for string objects and primitives");
ok(!_master.isEqual(new String("Curly"), new String("Larry")), "String objects with different primitive values are not equal");
ok(!_master.isEqual(new String("Curly"), {toString: function(){ return "Curly"; }}), "String objects and objects with a custom `toString` method are not equal");

// Number object and primitive comparisons.
ok(_master.isEqual(75, 75), "Identical number primitives are equal");
ok(_master.isEqual(new Number(75), new Number(75)), "Number objects with identical primitive values are equal");

ok(!_master.isEqual(75, new Number(75)), "Number primitives and their corresponding object wrappers are not equal");
ok(!_master.isEqual(new Number(75), 75), "Commutative equality is implemented for number objects and primitives");
ok(!_master.isEqual(new Number(75), new Number(63)), "Number objects with different primitive values are not equal");
ok(!_master.isEqual(new Number(63), {valueOf: function(){ return 63; }}), "Number objects and objects with a `valueOf` method are not equal");

// Comparisons involving `NaN`.
ok(_master.isEqual(NaN, NaN), "`NaN` is equal to `NaN`");
ok(!_master.isEqual(61, NaN), "A number primitive is not equal to `NaN`");
ok(!_master.isEqual(new Number(79), NaN), "A number object is not equal to `NaN`");
ok(!_master.isEqual(Infinity, NaN), "`Infinity` is not equal to `NaN`");

// Boolean object and primitive comparisons.
ok(_master.isEqual(true, true), "Identical boolean primitives are equal");
ok(_master.isEqual(new Boolean, new Boolean), "Boolean objects with identical primitive values are equal");
ok(!_master.isEqual(true, new Boolean(true)), "Boolean primitives and their corresponding object wrappers are not equal");
ok(!_master.isEqual(new Boolean(true), true), "Commutative equality is implemented for booleans");
ok(!_master.isEqual(new Boolean(true), new Boolean), "Boolean objects with different primitive values are not equal");

// Common type coercions.
ok(!_master.isEqual(true, new Boolean(false)), "Boolean objects are not equal to the boolean primitive `true`");
ok(!_master.isEqual("75", 75), "String and number primitives with like values are not equal");
ok(!_master.isEqual(new Number(63), new String(63)), "String and number objects with like values are not equal");
ok(!_master.isEqual(75, "75"), "Commutative equality is implemented for like string and number values");
ok(!_master.isEqual(0, ""), "Number and string primitives with like values are not equal");
ok(!_master.isEqual(1, true), "Number and boolean primitives with like values are not equal");
ok(!_master.isEqual(new Boolean(false), new Number(0)), "Boolean and number objects with like values are not equal");
ok(!_master.isEqual(false, new String("")), "Boolean primitives and string objects with like values are not equal");
ok(!_master.isEqual(12564504e5, new Date(2009, 9, 25)), "Dates and their corresponding numeric primitive values are not equal");

// Dates.
ok(_master.isEqual(new Date(2009, 9, 25), new Date(2009, 9, 25)), "Date objects referencing identical times are equal");
ok(!_master.isEqual(new Date(2009, 9, 25), new Date(2009, 11, 13)), "Date objects referencing different times are not equal");
ok(!_master.isEqual(new Date(2009, 11, 13), {
  getTime: function(){
    return 12606876e5;
  }
}), "Date objects and objects with a `getTime` method are not equal");
ok(!_master.isEqual(new Date("Curly"), new Date("Curly")), "Invalid dates are not equal");

// Functions.
ok(!_master.isEqual(First, Second), "Different functions with identical bodies and source code representations are not equal");

// RegExps.
ok(_master.isEqual(/(?:)/gim, /(?:)/gim), "RegExps with equivalent patterns and flags are equal");
ok(!_master.isEqual(/(?:)/g, /(?:)/gi), "RegExps with equivalent patterns and different flags are not equal");
ok(!_master.isEqual(/Moe/gim, /Curly/gim), "RegExps with different patterns and equivalent flags are not equal");
ok(!_master.isEqual(/(?:)/gi, /(?:)/g), "Commutative equality is implemented for RegExps");
ok(!_master.isEqual(/Curly/g, {source: "Larry", global: true, ignoreCase: false, multiline: false}), "RegExps and RegExp-like objects are not equal");

// Empty arrays, array-like objects, and object literals.
ok(_master.isEqual({}, {}), "Empty object literals are equal");
ok(_master.isEqual([], []), "Empty array literals are equal");
ok(_master.isEqual([{}], [{}]), "Empty nested arrays and objects are equal");
ok(!_master.isEqual({length: 0}, []), "Array-like objects and arrays are not equal.");
ok(!_master.isEqual([], {length: 0}), "Commutative equality is implemented for array-like objects");

ok(!_master.isEqual({}, []), "Object literals and array literals are not equal");
ok(!_master.isEqual([], {}), "Commutative equality is implemented for objects and arrays");

// Arrays with primitive and object values.
ok(_master.isEqual([1, "Larry", true], [1, "Larry", true]), "Arrays containing identical primitives are equal");
ok(_master.isEqual([/Moe/g, new Date(2009, 9, 25)], [/Moe/g, new Date(2009, 9, 25)]), "Arrays containing equivalent elements are equal");

// Multi-dimensional arrays.
var a = [new Number(47), false, "Larry", /Moe/, new Date(2009, 11, 13), ['running', 'biking', new String('programming')], {a: 47}];
var b = [new Number(47), false, "Larry", /Moe/, new Date(2009, 11, 13), ['running', 'biking', new String('programming')], {a: 47}];
ok(_master.isEqual(a, b), "Arrays containing nested arrays and objects are recursively compared");

// Overwrite the methods defined in ES 5.1 section 15.4.4.
a.forEach = a.map = a.filter = a.every = a.indexOf = a.lastIndexOf = a.some = a.reduce = a.reduceRight = null;
b.join = b.pop = b.reverse = b.shift = b.slice = b.splice = b.concat = b.sort = b.unshift = null;

// Array elements and properties.
ok(!_master.isEqual(a, b), "Arrays containing equivalent elements and different non-numeric properties are not equal");
a.push("White Rocks");
ok(!_master.isEqual(a, b), "Arrays of different lengths are not equal");
a.push("East Boulder");
b.push("Gunbarrel Ranch", "Teller Farm");
ok(!_master.isEqual(a, b), "Arrays of identical lengths containing different elements are not equal");
ready
Pull 351 Implementation
// Basic equality and identity comparisons.
ok(_351.isEqual(null, null), "`null` is equal to `null`");
ok(_351.isEqual(), "`undefined` is equal to `undefined`");

ok(!_351.isEqual(0, -0), "`0` is not equal to `-0`");
ok(!_351.isEqual(-0, 0), "Commutative equality is implemented for `0` and `-0`");
ok(!_351.isEqual(null, undefined), "`null` is not equal to `undefined`");
ok(!_351.isEqual(undefined, null), "Commutative equality is implemented for `null` and `undefined`");

// String object and primitive comparisons.
ok(_351.isEqual("Curly", "Curly"), "Identical string primitives are equal");
ok(_351.isEqual(new String("Curly"), new String("Curly")), "String objects with identical primitive values are equal");
ok(_351.isEqual(new String("Curly"), "Curly"), "String primitives and their corresponding object wrappers are equal");
ok(_351.isEqual("Curly", new String("Curly")), "Commutative equality is implemented for string objects and primitives");

ok(!_351.isEqual("Curly", "Larry"), "String primitives with different values are not equal");
ok(!_351.isEqual(new String("Curly"), new String("Larry")), "String objects with different primitive values are not equal");
ok(!_351.isEqual(new String("Curly"), {toString: function(){ return "Curly"; }}), "String objects and objects with a custom `toString` method are not equal");

// Number object and primitive comparisons.
ok(_351.isEqual(75, 75), "Identical number primitives are equal");
ok(_351.isEqual(new Number(75), new Number(75)), "Number objects with identical primitive values are equal");
ok(_351.isEqual(75, new Number(75)), "Number primitives and their corresponding object wrappers are equal");
ok(_351.isEqual(new Number(75), 75), "Commutative equality is implemented for number objects and primitives");

ok(!_351.isEqual(new Number(75), new Number(63)), "Number objects with different primitive values are not equal");
ok(!_351.isEqual(new Number(63), {valueOf: function(){ return 63; }}), "Number objects and objects with a `valueOf` method are not equal");

// Comparisons involving `NaN`.
ok(_351.isEqual(NaN, NaN), "`NaN` is equal to `NaN`");
ok(!_351.isEqual(61, NaN), "A number primitive is not equal to `NaN`");
ok(!_351.isEqual(new Number(79), NaN), "A number object is not equal to `NaN`");
ok(!_351.isEqual(Infinity, NaN), "`Infinity` is not equal to `NaN`");

// Boolean object and primitive comparisons.
ok(_351.isEqual(true, true), "Identical boolean primitives are equal");
ok(_351.isEqual(new Boolean, new Boolean), "Boolean objects with identical primitive values are equal");
ok(_351.isEqual(true, new Boolean(true)), "Boolean primitives and their corresponding object wrappers are equal");
ok(_351.isEqual(new Boolean(true), true), "Commutative equality is implemented for booleans");
ok(!_351.isEqual(new Boolean(true), new Boolean), "Boolean objects with different primitive values are not equal");

// Common type coercions.
ok(!_351.isEqual(true, new Boolean(false)), "Boolean objects are not equal to the boolean primitive `true`");
ok(!_351.isEqual("75", 75), "String and number primitives with like values are not equal");
ok(!_351.isEqual(new Number(63), new String(63)), "String and number objects with like values are not equal");
ok(!_351.isEqual(75, "75"), "Commutative equality is implemented for like string and number values");
ok(!_351.isEqual(0, ""), "Number and string primitives with like values are not equal");
ok(!_351.isEqual(1, true), "Number and boolean primitives with like values are not equal");
ok(!_351.isEqual(new Boolean(false), new Number(0)), "Boolean and number objects with like values are not equal");
ok(!_351.isEqual(false, new String("")), "Boolean primitives and string objects with like values are not equal");
ok(!_351.isEqual(12564504e5, new Date(2009, 9, 25)), "Dates and their corresponding numeric primitive values are not equal");

// Dates.
ok(_351.isEqual(new Date(2009, 9, 25), new Date(2009, 9, 25)), "Date objects referencing identical times are equal");
ok(!_351.isEqual(new Date(2009, 9, 25), new Date(2009, 11, 13)), "Date objects referencing different times are not equal");
ok(!_351.isEqual(new Date(2009, 11, 13), {
  getTime: function(){
    return 12606876e5;
  }
}), "Date objects and objects with a `getTime` method are not equal");
ok(!_351.isEqual(new Date("Curly"), new Date("Curly")), "Invalid dates are not equal");

// Functions.
ok(!_351.isEqual(First, Second), "Different functions with identical bodies and source code representations are not equal");

// RegExps.
ok(_351.isEqual(/(?:)/gim, /(?:)/gim), "RegExps with equivalent patterns and flags are equal");
ok(!_351.isEqual(/(?:)/g, /(?:)/gi), "RegExps with equivalent patterns and different flags are not equal");
ok(!_351.isEqual(/Moe/gim, /Curly/gim), "RegExps with different patterns and equivalent flags are not equal");
ok(!_351.isEqual(/(?:)/gi, /(?:)/g), "Commutative equality is implemented for RegExps");
ok(!_351.isEqual(/Curly/g, {source: "Larry", global: true, ignoreCase: false, multiline: false}), "RegExps and RegExp-like objects are not equal");

// Empty arrays, array-like objects, and object literals.
ok(_351.isEqual({}, {}), "Empty object literals are equal");
ok(_351.isEqual([], []), "Empty array literals are equal");
ok(_351.isEqual([{}], [{}]), "Empty nested arrays and objects are equal");
ok(!_351.isEqual({length: 0}, []), "Array-like objects and arrays are not equal.");
ok(!_351.isEqual([], {length: 0}), "Commutative equality is implemented for array-like objects");

ok(!_351.isEqual({}, []), "Object literals and array literals are not equal");
ok(!_351.isEqual([], {}), "Commutative equality is implemented for objects and arrays");

// Arrays with primitive and object values.
ok(_351.isEqual([1, "Larry", true], [1, "Larry", true]), "Arrays containing identical primitives are equal");
ok(_351.isEqual([/Moe/g, new Date(2009, 9, 25)], [/Moe/g, new Date(2009, 9, 25)]), "Arrays containing equivalent elements are equal");

// Multi-dimensional arrays.
var a = [new Number(47), false, "Larry", /Moe/, new Date(2009, 11, 13), ['running', 'biking', new String('programming')], {a: 47}];
var b = [new Number(47), false, "Larry", /Moe/, new Date(2009, 11, 13), ['running', 'biking', new String('programming')], {a: 47}];
ok(_351.isEqual(a, b), "Arrays containing nested arrays and objects are recursively compared");

// Overwrite the methods defined in ES 5.1 section 15.4.4.
a.forEach = a.map = a.filter = a.every = a.indexOf = a.lastIndexOf = a.some = a.reduce = a.reduceRight = null;
b.join = b.pop = b.reverse = b.shift = b.slice = b.splice = b.concat = b.sort = b.unshift = null;

// Array elements and properties.
ok(_351.isEqual(a, b), "Arrays containing equivalent elements and different non-numeric properties are equal");
a.push("White Rocks");
ok(!_351.isEqual(a, b), "Arrays of different lengths are not equal");
a.push("East Boulder");
b.push("Gunbarrel Ranch", "Teller Farm");
ok(!_351.isEqual(a, b), "Arrays of identical lengths containing different elements are not equal");
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.

  • Revision 1: published by Kit Cambridge on