DEV Community

Cover image for 5 Different Ways to Deep Compare JavaScript Objects
Suresh Mohan for Syncfusion, Inc.

Posted on • Originally published at syncfusion.com on

5 Different Ways to Deep Compare JavaScript Objects

JavaScript has 7 primitive data types. We can compare the values of any of these types using an equality operator. However, comparing non-primitive types such as objects is tricky since the usual equality operators do not compare object values as one might expect.

In this article, we will discuss five different ways to determine the equality of JavaScript objects.

Two types of equalities in JavaScript

When discussing object comparisons in JavaScript, there are two types of equalities one must be aware of:

  • *Referential equality: * Determines whether the two provided operands refer to the same reference/object instance.
  • *Deep equality: * Determines whether objects are equal by comparing each property in the operands.

Referential equality can be determined with equality operators such as strict equality (===) or coercive equality (==) and also by using Object.is() functions, but determining deep equality is tricky as the objects can be nested. However, the following five ways of performing object comparisons make developers’ work easier when a deep equality comparison is required.

Manual comparison

The apparent first thought on anyone’s mind for this problem would be to take each property and compare it against the other operand’s properties and values. But, as mentioned before, these objects can have nested properties. Hence, we have to use a recursive method to compare these nested objects.

A recursive method implementation like the following should be able to tell us whether two given objects are deep equal .

const person1 = {
    "firstName": "John",
    "lastName": "Doe",
    "age": 35 
};

const person2 = {
    "firstName": "John",
    "lastName": "Doe",
    "age": 35,
};

const isDeepEqual = (object1, object2) => {

  const objKeys1 = Object.keys(object1);
  const objKeys2 = Object.keys(object2);

  if (objKeys1.length !== objKeys2.length) return false;

  for (var key of objKeys1) {
    const value1 = object1[key];
    const value2 = object2[key];

    const isObjects = isObject(value1) && isObject(value2);

    if ((isObjects && !isDeepEqual(value1, value2)) ||
      (!isObjects && value1 !== value2)
    ) {
      return false;
    }
  }
  return true;
};

const isObject = (object) => {
  return object != null && typeof object === "object";
};

console.log(isDeepEqual(person1, person2)); //true
Enter fullscreen mode Exit fullscreen mode

JSON.stringify() method

This method is more of a trick that we can use to determine whether two objects are deep equal or not. Even though JavaScript does not have an out-of-the-box solution to compare two objects, it has no problem comparing two strings. Therefore, in this method, we convert our two objects into strings using the JSON.stringify() method and compare the two values to determine whether the objects are deep equal. Even if the objects have nested properties, this method can handle those as well. It is important to note that this method uses strict equality (===) on attributes; therefore, having ages as 35 and “35” will not be equal.

const person1 = {
    "firstName": "John",
    "lastName": "Doe",
    "age": 35 
}

const person2 = {
    "firstName": "John",
    "lastName": "Doe",
    "age": 35 
}

JSON.stringify(person1) === JSON.stringify(person2); // true
Enter fullscreen mode Exit fullscreen mode

This method has one downside, however. Take the above example and alter the order of the attributes in the object person2.

const person2= {
    "age": 35,
    "firstName": "John",
    "lastName": "Doe"
}
Enter fullscreen mode Exit fullscreen mode

Since the object attributes and their values have not changed, we would expect to return true when the objects are compared. Since the generated strings are different this time due to the difference in the order, the comparison will return false.

Therefore, it is important to note that having different orders of attributes can give incorrect results when using this method.

Comparisons using Lodash library

The famous Lodash library also provides a method to determine deep equality between two objects. Using the isEqual() method from this library, we can perform a deep comparison between the given operands. It will return a Boolean value indicating whether the operands are equal based on JavaScript strict equality (===) on all attributes of the two given objects.

const _ = require('lodash');

const person1 = {
    "firstName": "John",
    "lastName": "Doe",
    "age": 35 
}

const person2 = {
    "firstName": "John",
    "lastName": "Doe",
    "age": 35 
}

_.isEqual(person1, person2); // true
Enter fullscreen mode Exit fullscreen mode

According to the Lodash documentation, this method supports arrays, array buffers, date objects, etc. As a bonus, we can download this method as a separate npm module as well.

Comparisons using the deep-equal library

The deep-equal library is another vastly popular NPM module with over 11 million weekly downloads. This library provides the functionality to determine deep equality between two objects.

The deepEqual() method from the library takes three parameters. The first two are the operands to be compared, and the third parameter is an optional options parameter. With the option, we can specify whether to use strict equality (===) or coercive equality (==) to compare the leaf nodes. The default option is to use coercive equality to compare leaf nodes.

const deepEqual = require('deep-equal');

const person1 = {
    "firstName": "John",
    "lastName": "Doe",
    "age": 35 
}

const person2 = {
    "firstName": "John",
    "lastName": "Doe",
    "age": "35" 
}
deepEqual(person1, person2); // true
Enter fullscreen mode Exit fullscreen mode

Note that the age value is a number in the person1 object and a string in the person2 object. Since the strict option is false by default, the deep-equal library uses coercive equality on the leaf nodes, so this function returns true. If the strict parameter of the function is set to true , this method would return false.

const person2 = {
    "firstName": "John",
    "lastName": "Doe",
    "age": "35" 
}

deepEqual(person1, person2, {strict: true}); // false

//When person2 values are updated with the same data types as person1.
const person2 = {
    "firstName": "John",
    "lastName": "Doe",
    "age": 35 
}

deepEqual(person1, person2, {strict: true}); // true
Enter fullscreen mode Exit fullscreen mode

Framework-specific methods

Some JavaScript frameworks, such as Angular and Nodejs, provide built-in functionality to determine deep equality in their frameworks.

  • Node.js : assert.deepStrictEqual(actual, expected, message) The deepStrictEqual() method provided by the assert module is a built-in method in Node.js that takes three parameters: the two operands and a message as an optional parameter that will be used when an error is thrown if the two operands are not equal. This method will check for strict equality on leaf nodes. It will return undefined if the operands are equal and will throw an error if they are not deep and strictly equal.
const assert = require('assert');

const person1 = {
    "firstName": "John",
    "lastName": "Doe",
    "age": 35 
}

const person2 = {
    "firstName": "John",
    "lastName": "Doe",
    "age": 35 
}

console.log(assert.deepStrictEqual(person1, person2)); //true
Enter fullscreen mode Exit fullscreen mode
  • Angular : angular.equals(obj1, obj2) The Angular library also provides a method that helps us to determine deep equality between two objects. This method is provided under the ng module. It takes two parameters, the operands, to be compared for equality and returns a Boolean value indicating whether the operands are equal based on JavaScript strict equality (===).
var person1 = {
  firstName: "John",
  lastName: "Doe",
  age: 35,
};

var person2 = {
  firstName: "John",
  lastName: "Doe",
  age: 35,
};

console.log(angular.equals(person1, person2)); //true
Enter fullscreen mode Exit fullscreen mode

Conclusion

JavaScript deep object comparison can be tricky, so careful handling is required. As discussed above, there are many methods, including third-party libraries, that help us to determine deep equality between objects. To select the suitable method for a use case, one must consider each method’s requirements and options.

I hope this article will help you to make the right decision. Thank you for reading.

Syncfusion Essential JS 2 is the only suite you will ever need to build an app. It contains over 65 high-performance, lightweight, modular, and responsive UI components in a single package. Download a free trial to evaluate the controls today.

If you have any questions or comments, you can contact us through our support forums, support portal, or feedback portal. We are always happy to assist you!

Related blogs

Top comments (0)