DEV Community

Cover image for Object Equality in JavaScript
Jatin Panjwani
Jatin Panjwani

Posted on

Object Equality in JavaScript

Object comparison in javascript works a bit differently than primitive value comparison.

Objects are compared by reference while primitives are compared by value.

For example,

const obj1 = { name: 'John', age: 25 };
const obj2 = { name: 'John', age: 25 };

console.log(obj1 === obj2); // false

// primitive value comparison
const a = 10;
const b = 10;

const name = 'Jack';
const surname = 'Jack';

console.log(a === b); // true
console.log(name === surname); // true
Enter fullscreen mode Exit fullscreen mode

Since the above objects are compared by reference which means both are stored at different memory locations.

So there are two different ways to compare objects:

  • Shallow Equality
  • Deep Equality

Shallow Equality

JSON.stringify()

This is the first method that comes to my mind when looking to compare two objects, though this approach has several limitations. It is useful in cases where the order of the keys of two given objects are the same.

For example,

const person1 = { 
                  name: 'jack dorsey',
                  founded: 'twitter', 
                  addresses: ['new york', 'boston'] 
                };
const person2 = { 
                  name: 'jack dorsey',
                  founded: 'twitter', 
                  addresses: ['new york', 'boston'] 
                };

console.log(JSON.stringify(person1) === JSON.stringify(person2)); // true

// order of key changes
const person3 = { 
                  founded: 'twitter', 
                  addresses: ['new york', 'boston'],
                  name: 'jack dorsey'
                };

console.log(JSON.stringify(person3) === JSON.stringify(person2)); // false
Enter fullscreen mode Exit fullscreen mode

Custom isEqual check

function isEqual(obj1, obj2) {
  if (Object.keys(obj1).length !== Object.keys(obj2).length) return false;

  for (let [key, value] of Object.entries(obj1)) {
    if (!obj2[key] || obj2[key] !== value) {
      return false;
    }
  }

  return true;
}

console.log(isEqual({
                     name:'hela',
                     age: 5000
                    }, 
                    {
                     name:'hela', 
                     age: 5000
                    })); // true

console.log(isEqual({
                     name:'hela',
                     age: 5000, 
                     power: 90000
                     }, 
                     {
                      name:'hela', 
                      age: 5000
                     })); // false

console.log(isEqual({
                     name:'hela',
                     age: 5000
                    }, 
                    {
                     name:'hela', 
                     age: 4000
                    })); // false
Enter fullscreen mode Exit fullscreen mode

But the above method has a major limitation which is if some key has an object or array as its value then this method breaks.

For example,

console.log(isEqual({
              name: 'Shazam',
              age: 15,
              superpowers: ['flying', 'thundershock']
            },
            {
             name: 'Shazam',
             age: 15,
             superpowers: ['flying', 'thundershock']
            })); // false
Enter fullscreen mode Exit fullscreen mode

Deep Equality

This approach helps solve the limitation faced by above method.

const person1 = {
    name: 'Jatin',
    age: 25,
    address: {
        city: 'Mundra',
        state: 'Gujarat',
        nation: 'India'
    }
}

const person2 = {
    name: 'Jatin',
    age: 25,
    address: {
        city: 'Mundra',
        nation: 'India',
        state: 'Gujarat'
    }
}

const person3 = {
    name: 'Jatin',
    age: 25,
    address: {
        city: 'Baroda',
        nation: 'India',
        state: 'Gujarat'
    }
}

function isDeepEqual(obj1, obj2) {
    if (Object.keys(obj1).length !== Object.keys(obj2).length) return false;

    for (let [key, value] of Object.entries(obj1)) {
        if (!obj2[key]) {
            return false;
        } else {
            if (typeof obj2[key] === 'object' && typeof value === 'object') {
                return isDeepEqual(obj2[key], value);
            } else if (typeof obj2[key] !== 'object' && typeof value !== 'object') {
                if (obj2[key] !== value) {
                    return false;
                }
            } else {
                return false;
            }
        }
    }

    return true;
}

isDeepEqual(person1, person2); // true
isDeepEqual(person2, person3); // false
Enter fullscreen mode Exit fullscreen mode

Parting Notes

This problem is covered well by libraries like Lodash, Underscore. This problem is a favorite interview question for entry level javascript engineers. Thanks for taking the time to read this. I'd love some feedback. All the best for your upcoming interview.

Top comments (3)

Collapse
 
utkarshkpal profile image
Utkarsh Kandpal • Edited

Good article . Although, your isDeepEqual() function is slightly incorrect.
when we check for a nested property the function returns true preemptively without checking further key , value pair.
test case for which it is failing : (returns true although it should return false)

const person1 = {
address: {
city: 'Mundra',
state: 'Gujarat',
nation: 'India'
},
name: 'Jatin',
age: 25,

}

const person2 = {
address: {
city: 'Mundra',
nation: 'India',
state: 'Gujarat'
},
name: 'Jatin',
age: 27,

}

Collapse
 
jatin33 profile image
Jatin Panjwani

nice catch

Collapse
 
mohsenalyafei profile image
Mohsen Alyafei

Thank you. This is helpful and useful.