Compare two JavaScript Objects
Use the JSON.stringify()
method to compare two or more objects. It is the easiest way to compare objects in JavaScript.
Basically, the JSON.stringify() method converts an object into a string, and that’s how we compare the objects as strings.
const a = {
name:"John",
email:"[email protected]"
}
const b = {
name:"John",
email:"[email protected]"
}
console.log(JSON.stringify(a) === JSON.stringify(b));
true
Issue with JSON.stringify()
The JSON.stringify()
will not work If an object contains methods or dom nodes.
Because, when you convert an object to a string using JSON.stringify()
it does not preserve methods and DOM nodes.
const a = {
name:"John",
test:function(){
return "Test";
}
}
console.log(JSON.stringify(a));
{"name":"John"}
Deep comparison of javascript objects
There is an awesome code posted by crazyx on StackOverflow that compares two javascript objects deeply.
Note: The performance will depend on the size/depth of the objects.
const a = {
name:"John",
test:function(){
return false;
}
}
const b = {
name:"John",
test:function(){
return true;
}
}
console.log(deepCompare(a, b));
// Created By crazyx - https://tinyurl.com/mpen7wn6
function deepCompare() {
var i, l, leftChain, rightChain;
function compare2Objects(x, y) {
var p;
// remember that NaN === NaN returns false
// and isNaN(undefined) returns true
if (
isNaN(x) &&
isNaN(y) &&
typeof x === "number" &&
typeof y === "number"
) {
return true;
}
// Compare primitives and functions.
// Check if both arguments link to the same object.
// Especially useful on the step where we compare prototypes
if (x === y) {
return true;
}
// Works in case when functions are created in constructor.
// Comparing dates is a common scenario. Another built-ins?
// We can even handle functions passed across iframes
if (
(typeof x === "function" && typeof y === "function") ||
(x instanceof Date && y instanceof Date) ||
(x instanceof RegExp && y instanceof RegExp) ||
(x instanceof String && y instanceof String) ||
(x instanceof Number && y instanceof Number)
) {
return x.toString() === y.toString();
}
// At last checking prototypes as good as we can
if (!(x instanceof Object && y instanceof Object)) {
return false;
}
if (x.isPrototypeOf(y) || y.isPrototypeOf(x)) {
return false;
}
if (x.constructor !== y.constructor) {
return false;
}
if (x.prototype !== y.prototype) {
return false;
}
// Check for infinitive linking loops
if (leftChain.indexOf(x) > -1 || rightChain.indexOf(y) > -1) {
return false;
}
// Quick checking of one object being a subset of another.
// todo: cache the structure of arguments[0] for performance
for (p in y) {
if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {
return false;
} else if (typeof y[p] !== typeof x[p]) {
return false;
}
}
for (p in x) {
if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {
return false;
} else if (typeof y[p] !== typeof x[p]) {
return false;
}
switch (typeof x[p]) {
case "object":
case "function":
leftChain.push(x);
rightChain.push(y);
if (!compare2Objects(x[p], y[p])) {
return false;
}
leftChain.pop();
rightChain.pop();
break;
default:
if (x[p] !== y[p]) {
return false;
}
break;
}
}
return true;
}
if (arguments.length < 1) {
return true; //Die silently? Don't know how to handle such case, please help...
// throw "Need two or more arguments to compare";
}
for (i = 1, l = arguments.length; i < l; i++) {
leftChain = []; //Todo: this can be cached
rightChain = [];
if (!compare2Objects(arguments[0], arguments[i])) {
return false;
}
}
return true;
}
false