JS: Test Equality of Objects

By Xah Lee. Date: . Last updated: .

This page shows you a function to compare equality of objects by deep dive.

JavaScript doesn't have a buildin way to compare equality of 2 objects.

const c = {"a":3};
const d = {"a":3};

console.log( c === d ); // false

When a object is assigned to a variable, the variable holds a reference to the object.

If 2 variables hold the same reference, they are equal.

but 2 objects with same property and parent etc, will have different reference.

const x = {"a":3};
const y = x; // x and y holds the same reference

console.log( x === y ); // true

const z = {"a":3};

console.log( z === y ); // false

console.log( z === x ); // false

console.log(z); // {a:3}
console.log(y); // {a:3}

Function to Test Object Equality

Here's functions to compare object equality.

/* [
xah_is_obj_equal(obj1, obj2)
Return true if 2 objects are equal.
Equal here means deep compare enumerable properties of object

http://xahlee.info/js/js_comparison_equality_test_objects.html
version 2019-04-24
 ] */
const xah_is_obj_equal = ((obj1, obj2) =>
{
    const keys1 = Object.keys(obj1).sort();
    const keys2 = Object.keys(obj2).sort();

    if ( keys1.length !== keys2.length  ) {
        return false;
    }

    // first make sure have same keys. may save time
    if ( ! keys1.every( ((k, i) => (k === keys2[i])) ) ) {
        return false;
    }

    // check if any value is not equal
    return keys1.every ( ((kk) => {
        const v1 = obj1[kk];
        const v2 = obj2[kk];
        if ( Array.isArray(v1) )  {
            return xah_is_array_equal(v1,v2);
        } else if ( typeof v1 === "object" && v1 !== null) {
            return xah_is_obj_equal(v1,v2);
        } else {
            return v1 === v2;
        }
    })  );
});

/* [
xah_is_array_equal(array1, array2)
Return true if 2 array are equal
Allow array-like object
Allow nested array

http://xahlee.info/js/js_comparison_equality_test_objects.html
version 2019-04-24
 ] */
const xah_is_array_equal = ((array1, array2) =>
{
    // allow array-like object
    if ( Array.isArray(array1) !== Array.isArray(array2) ) { return false; }
    if (array1.length !== array2.length) { return false; }

    return Array.prototype.every.call(
        array1,
        ((x, i) => {
            const y = array2[i];
            if ( Array.isArray(x) ) {
                if ( ! Array.isArray(y) ) {
                    return false;}
                else {
                    return xah_is_array_equal(x, y); }
            } else if ( typeof x === "object" && typeof x !== null) {
                if (! ( typeof y === "object" && typeof y !== null)) {
                    return false;}
                else {
                    return xah_is_obj_equal(x,y); }
            } else {
                return (x === y);
            }
        })
    );
});

// ------------------------------------------------------
// tests

console.log(
    // simple obj
    xah_is_obj_equal({"a":1}, {"a":1}),

    // diff value
    ! xah_is_obj_equal({"a":1}, {"a":2}),

    // num of obj not same
    ! xah_is_obj_equal({"a":1,"b":2}, {"a":1}),

    // diff order
    xah_is_obj_equal({"a":1,"b":2}, {"b":2,"a":1}),

    // test empty obj
    xah_is_obj_equal({}, {}),

    // nested obj
    xah_is_obj_equal(
        {"a":1,"b":{"c":3}},
        {"a":1,"b":{"c":3}})
);

// nested obj with diff value
console.log(
    ! xah_is_obj_equal(
        {"a":1,"b":{"c":1}},
        {"a":1,"b":{"c":2}})
,
// deeper nesting
    xah_is_obj_equal(
        {"a":1,"b":{"c":3, "mm":{"x1":1,"x2":{"x3":3}}}},
        {"a":1,"b":{"c":3, "mm":{"x1":1,"x2":{"x3":3}}}})
,
// works on array-like obj
    xah_is_obj_equal(
        {0:3,1:4,"length":2},
        {0:3,1:4,"length":2})
,
// works on array obj
    xah_is_obj_equal(
        [3, {0:3,1:4,"length":2}, [[2,7],9]],
        [3, {0:3,1:4,"length":2}, [[2,7],9]])
);

// ----------------------------------------------

// test on array objects
console.log (
    xah_is_array_equal([3,4], [3,4])
    ,
    ! xah_is_array_equal([3,4], [4,3])
    ,
    ! xah_is_array_equal([3,4], [3])
    ,
    xah_is_array_equal([], [])
    ,
    // array-like objects
    xah_is_array_equal(
        {0:3,1:4,"length":2},
        {0:3,1:4,"length":2}
    )
    ,
    // nested array
    xah_is_array_equal(
        [3,4, [[2,7],9]],
        [3,4, [[2,7],9]])
    ,
    // negation
    ! xah_is_array_equal(
        [3,4, {"t":2}],
        [3,4, {"t":2, "b":2}])
    ,
    xah_is_array_equal(
        [ {"b":1},4],
        [ {"b":1},4])
);

Comparison by JSON, Ordering Problem

If you turn object into JSON string, then compare the string, this is not reliable because object properties is not ordered.

// comparison by JSON.stringify is not reliable

const x = {"a":1, "b":2};
const y = {"b":2, "a":1}; // reverse order

console.log( JSON.stringify(x) === JSON.stringify(y) ); // false

see also JS: Compare Array Equality

JS Array

  1. Understand JS Array
  2. Create Array
  3. Sparse Array
  4. Array-Like Object
  5. Array How-To

JS Object and Inheritance

  1. Object Overview
  2. Object Type
  3. Find Object's Type
  4. Prototype Chain
  5. Create Object
  6. Object Literal Expr
  7. Create Object with Parent X
  8. Get/Set Parent
  9. Show Prototype Chain
  10. Prevent Adding Property
  11. Clone Object
  12. Test Object Equality
  13. Add Method to Prototype

Like it? Help me by telling your friends. Or, Put $5 at patreon.

Or, Buy JavaScript in Depth

If you have a question, put $5 at patreon and message me.

Web Dev Tutorials

  1. HTML
  2. Visual CSS
  3. JS in Depth
  4. JS Object Ref
  5. DOM Scripting
  6. SVG
  7. Blog