compare two JavaScript Objects

How to compare two JavaScript Objects?

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