DEV Community

Cover image for Comparing Values of Objects in JavaScript 🧭
Nemo
Nemo

Posted on • Originally published at blog.nemotivity.xyz

Comparing Values of Objects in JavaScript 🧭

JavaScript has only two data types. One is Primitive, and the other one is the non-primitive data type. Primitive data types consist of

  • undefined
  • Boolean
  • Number
  • String
  • Symbol
  • null

And Non-Primitive data types have only one member, i.e.,

  • Object

More about JavaScript data types here.

Comparing primitive data types is easy. We can quickly compare two primitive data types using the equality operator. But it doesn't work for non-primitive types. Because primitive data types are compared by their values, while objects in JavaScript are compared by their reference, so, the simple equality operator will only check if the location of the two objects is the same or not. We'll understand it with a code example here.

Checking two Objects using Equality Operator

Suppose we have two objects, i.e.,

let obj1 = {key1: "a", key2: "b", key3: "c"}
let obj2 = {key1: "a", key2: "b", key3: "c"}

We can see both the objects has the same key and values. Now if we try to write a function using the equality operator.

let isSame = (object1, object2) => {
  return object1 === object2;
}

If we run this function and provide obj and obj2 as parameters, the function will return false.

1

But if we define another variable that refers to an already defined object, it'll return true.

2

Here, obj1 and obj3 refer to the same memory location, and hence the function returns true.

Now I think we are much clear why we shouldn't use the simple equality operator while comparing two objects.

Multiple ways can be used to compare two objects. Let's see with examples.

Code Example 1

let areEqual = (object1, object2) => {
    return 
    object1.key1 === object2.key1 && 
    object1.key2 === object2.key2 && 
    object1.key3 === object2.key3 //and so on
}

This function will return true if two objects are equal. This code works, but it is way too static. We have to manually change each value for every different object having different key-value pairs.

To ease our work, we'll use the JSON.stringify method.

What is JSON.stringify

The JSON.stringify is a JavaScript method that converts a JavaScript object to a JSON string.

Syntax

JSON.stringify(value[, replacer[, space]])

The value specifies the value that has to be converted. The replacer and the space are optional arguments. You can check this article to know more about this method.

Code Example 2

let areEqual = (object1, object2) => {
  return JSON.stringify(object1) === JSON.stringify(object2) 
}

As we can see, that code is just a single line, and we can use this function with any two objects. We don't have to manually set up the parameters that are to be checked.

I hope you liked the article.

Top comments (7)

Collapse
 
pentacular profile image
pentacular

Because primitive data types are compared by their values, while objects in JavaScript are compared by their reference, so, the simple equality operator will only check if the location of the two objects is the same or not.

Objects in Javascript are compared by their value, just like any other value -- there is no 'object reference' in javascript.

What you've missed here is that the properties associated with an object are not part of the object's value.

let areEqual = (object1, object2) => {
return
object1.key1 === object2.key1 &&
object1.key2 === object2.key2 &&
object1.key3 === object2.key3 //and so on
}

With this code you're not checking to see if the object's are equal -- you're checking to see if two objects have properties with the same names and values.

This should also make it clear that this isn't how object equality works, because if it were, you'd need to recurse through each of those properties using areEqual, rather than using === to compare object values. :)

So, let's be clear.

  1. a === b compares two object values, just like it does non-object values.
  2. object values are independent of the properties associated with the object.
  3. testing to see if objects have equivalent properties associated needs to consider deep and shallow equivalence, and is not the same as comparing value.

As we can see, that code is just a single line, and we can use this function with any two objects.

Not exactly -- JSON.stringify won't work on objects with cyclic property structures.

e.g.

const a = {};
a.a = a;
JSON.stringify(a); // boom

JSON.stringify also only produces (unsurprisingly) things that can be represented in JSON, which excludes a number of javascript types --- for example, undefined and Symbol.

It will also lose information such as prototypical inheritance structures.

Collapse
 
nemo011 profile image
Nemo

Thank you a lot for sharing so much. I really appreciate it. And also learnt a lot l! Thanks again for correcting me. 😊

Collapse
 
devdufutur profile image
Rudy Nappée

You can't trust json stringify to compare objects... Stringified { a: 1, b: 2 } will be different than { b: 2, a: 1 } which isn't what you want.

Tuple and records will allow you to do that the simplest way. Check this proposal and it's polyfill : github.com/tc39/proposal-record-tuple

Collapse
 
nemo011 profile image
Nemo

Thanks for correcting me. Will definitely check and update the article. 😊

Collapse
 
devdufutur profile image
Rudy Nappée

You can do something like that if you want a generic function :

function areEquals(o1, o2) {
  if (!o1 || !o2) {
    return false;
  }
  return Object.keys(o1).length === Object.keys(o2).length 
    && Object.entries(o1).every(([key, value]) => {
      return key in o2 && o2[key] === value;
    });
}

console.log(areEquals({a: 1, b: 2}, {b: 2, a: 1})); // true
console.log(areEquals({a: 1}, {b: 2, a: 1})); // false
console.log(areEquals({a: 2}, {a: 1})); // false

If you wan't to go deeper and compare values in nested objects you can do :

function areDeepEquals(o1, o2) {
  if (!o1 || !o2) {
    return false;
  }
  return Object.keys(o1).length === Object.keys(o2).length 
    && Object.entries(o1).every(([key, value]) => {
      if (typeof value === "object") {
        return areDeepEquals(value, o2[key]);
      }
      return key in o2 && o2[key] === value;
    });
}

console.log(areDeepEquals({a: 1, b: 2, c: {d: 1}}, {b: 2, a: 1, c: {d: 1}})); // true
console.log(areDeepEquals({a: 1, b: 2, c: {d: 1}}, {b: 2, a: 1, c: {e: 1}})); // false
console.log(areDeepEquals({a: 1, b: 2, c: {d: 1}}, {b: 2, a: 1, c: {d: 2}})); // false
Thread Thread
 
devdufutur profile image
Rudy Nappée

Or you can use lodash isEqual() function !

Thread Thread
 
nemo011 profile image
Nemo

Okay! I'll keep it in mind. Thanks. 😊