Object Equality in JavaScript
Tags: javascript, beginners, interview
Published: 2020-07-25 11:01:25

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,
```javascript
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
```
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,
```javascript
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
```
### Custom isEqual check

```javascript
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
```

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,

```javascript
console.log(isEqual({
              name: 'Shazam',
              age: 15,
              superpowers: ['flying', 'thundershock']
            },
            {
             name: 'Shazam',
             age: 15,
             superpowers: ['flying', 'thundershock']
            })); // false
```
## Deep Equality
This approach helps solve the limitation faced by above method.

```javascript
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
```

## Parting Notes
This problem is covered well by libraries like [Lodash](https://lodash.com/), [Underscore](https://underscorejs.org/). 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.