Categories
equals hashcode javascript object

How to determine equality for two JavaScript objects?

889

A strict equality operator will tell you if two object types are equal. However, is there a way to tell if two objects are equal, much like the hash code value in Java?

Stack Overflow question Is there any kind of hashCode function in JavaScript? is similar to this question, but requires a more academic answer. The scenario above demonstrates why it would be necessary to have one, and I’m wondering if there is any equivalent solution.

12

  • 5

    Also look into this question stackoverflow.com/q/1068834/1671639

    – Praveen

    May 6, 2014 at 9:48


  • 51

    Note that, even in Java, a.hashCode() == b.hashCode() does not imply that a is equal to b. It’s a necessary condition, not a sufficient one.

    – Heinzi

    Sep 24, 2014 at 13:34


  • 5

    If you HAVE to compare objects in your code than you are probably writing your code wrong. The better question might be: “How can I write this code so I don’t have to compare objects?”

    – th317erd

    Feb 24, 2017 at 17:50

  • 9

    @th317erd can you please explain yourself?…

    – El Mac

    May 14, 2018 at 12:44

  • 1

    @ElMac I can’t speak directly for the person but I do agree with the statement and my thought process is that very often JS objects are fairly big. You rarely have something with very few properties like person = { name: "fred", age: 42 }. If you do and you have to search them by exact equality, it seems like a waste. Most often your plain objects will still have a lot of properties – and one either one is uinique or you want one to be unique, e.g., ID of some sort. You can then search by that and you don’t need to check if every single thing matches.

    – VLAZ

    May 14, 2018 at 21:01

218

The short answer

The simple answer is: No, there is no generic means to determine that an object is equal to another in the sense you mean. The exception is when you are strictly thinking of an object being typeless.

The long answer

The concept is that of an Equals method that compares two different instances of an object to indicate whether they are equal at a value level. However, it is up to the specific type to define how an Equals method should be implemented. An iterative comparison of attributes that have primitive values may not be enough: an object may contain attributes which are not relevant to equality. For example,

 function MyClass(a, b)
 {
     var c;
     this.getCLazy = function() {
         if (c === undefined) c = a * b // imagine * is really expensive
         return c;
     }
  }

In this above case, c is not really important to determine whether any two instances of MyClass are equal, only a and b are important. In some cases c might vary between instances and yet not be significant during comparison.

Note this issue applies when members may themselves also be instances of a type and these each would all be required to have a means of determining equality.

Further complicating things is that in JavaScript the distinction between data and method is blurred.

An object may reference a method that is to be called as an event handler, and this would likely not be considered part of its ‘value state’. Whereas another object may well be assigned a function that performs an important calculation and thereby makes this instance different from others simply because it references a different function.

What about an object that has one of its existing prototype methods overridden by another function? Could it still be considered equal to another instance that it otherwise identical? That question can only be answered in each specific case for each type.

As stated earlier, the exception would be a strictly typeless object. In which case the only sensible choice is an iterative and recursive comparison of each member. Even then one has to ask what is the ‘value’ of a function?

11

  • 206

    If you’re using underscore, you can just do _.isEqual(obj1, obj2);

    – chovy

    Aug 21, 2013 at 21:38

  • 15

    @Harsh, the answer failed to give any solution because there is none. Even in Java, there is no silver bullet to object equality comparison and to correctly implement the .equals method is not trivial, which is why there is such a topic dedicated in Effective Java.

    – lcn

    Sep 25, 2013 at 17:44

  • 4

    @Kumar Harsh, What makes two objects equal is very application specific; not every property of an object should necessarily be taken into consideration, so brute-forcing every property of an object is not a concrete solution either.

    – sethro

    Jan 17, 2014 at 22:05

  • googled javascript equality object, got tl;dr reply, took one-liner from @chovy comment. thank you

    – Andrea

    Apr 23, 2014 at 14:54

  • 1

    What is underscore? Is it a library? What is the minimum size code snippet for checking object equality?

    Dec 18, 2020 at 2:14

218

The short answer

The simple answer is: No, there is no generic means to determine that an object is equal to another in the sense you mean. The exception is when you are strictly thinking of an object being typeless.

The long answer

The concept is that of an Equals method that compares two different instances of an object to indicate whether they are equal at a value level. However, it is up to the specific type to define how an Equals method should be implemented. An iterative comparison of attributes that have primitive values may not be enough: an object may contain attributes which are not relevant to equality. For example,

 function MyClass(a, b)
 {
     var c;
     this.getCLazy = function() {
         if (c === undefined) c = a * b // imagine * is really expensive
         return c;
     }
  }

In this above case, c is not really important to determine whether any two instances of MyClass are equal, only a and b are important. In some cases c might vary between instances and yet not be significant during comparison.

Note this issue applies when members may themselves also be instances of a type and these each would all be required to have a means of determining equality.

Further complicating things is that in JavaScript the distinction between data and method is blurred.

An object may reference a method that is to be called as an event handler, and this would likely not be considered part of its ‘value state’. Whereas another object may well be assigned a function that performs an important calculation and thereby makes this instance different from others simply because it references a different function.

What about an object that has one of its existing prototype methods overridden by another function? Could it still be considered equal to another instance that it otherwise identical? That question can only be answered in each specific case for each type.

As stated earlier, the exception would be a strictly typeless object. In which case the only sensible choice is an iterative and recursive comparison of each member. Even then one has to ask what is the ‘value’ of a function?

11

  • 206

    If you’re using underscore, you can just do _.isEqual(obj1, obj2);

    – chovy

    Aug 21, 2013 at 21:38

  • 15

    @Harsh, the answer failed to give any solution because there is none. Even in Java, there is no silver bullet to object equality comparison and to correctly implement the .equals method is not trivial, which is why there is such a topic dedicated in Effective Java.

    – lcn

    Sep 25, 2013 at 17:44

  • 4

    @Kumar Harsh, What makes two objects equal is very application specific; not every property of an object should necessarily be taken into consideration, so brute-forcing every property of an object is not a concrete solution either.

    – sethro

    Jan 17, 2014 at 22:05

  • googled javascript equality object, got tl;dr reply, took one-liner from @chovy comment. thank you

    – Andrea

    Apr 23, 2014 at 14:54

  • 1

    What is underscore? Is it a library? What is the minimum size code snippet for checking object equality?

    Dec 18, 2020 at 2:14

191

The default equality operator in JavaScript for Objects yields true when they refer to the same location in memory.

var x = {};
var y = {};
var z = x;

x === y; // => false
x === z; // => true

If you require a different equality operator you’ll need to add an equals(other) method, or something like it to your classes and the specifics of your problem domain will determine what exactly that means.

Here’s a playing card example:

function Card(rank, suit) {
  this.rank = rank;
  this.suit = suit;
  this.equals = function(other) {
     return other.rank == this.rank && other.suit == this.suit;
  };
}

var queenOfClubs = new Card(12, "C");
var kingOfSpades = new Card(13, "S");

queenOfClubs.equals(kingOfSpades); // => false
kingOfSpades.equals(new Card(13, "S")); // => true

6

  • If the object(s) can be converted to a JSON string, then it makes an equals() function simple.

    – scotts

    Nov 14, 2012 at 18:28

  • 4

    @scotts Not always. Converting objects to JSON and comparing strings can become computationally intensive for complex objects in tight loops. For simple objects it probably doesn’t matter much, but in reality it truly depends on your specific situation. A correct solution may be as simple as comparing object IDs or checking each property, but its correctness is dictated entirely by the problem domain.

    Nov 14, 2012 at 19:32

  • 1

    Shouldn’t we compare the data type as well?! return other.rank === this.rank && other.suit === this.suit;

    Oct 28, 2013 at 14:59


  • 1

    @devsathish probably not. In JavaScript types are pretty fast and loose, but if in your domain types are important then you may want to check types as well.

    Oct 28, 2013 at 23:27

  • 15

    @scotts Other problem with converting to JSON is that the order of the properties in the string becomes significant. {x:1, y:2} !== {y:2, x:1}

    Mar 1, 2016 at 21:51