JS: Test Equality of Array and Object by Content 📜
Here's a function to compare equality of objects by comparing every element.
This is most useful for data objects. (such as comparing JSON objects with arbitrarily nested object or array.)
/* xah_is_obj_equal(xaa, xbb) Return true if every enumerable property keys and values are equal. (symbol keys are ignored), nested objects are compared the same way. Order of properties does not matter. Argument may be Object, true array, Array-like objects. If one is true array and the other array-like, return false. * For true arrays, index are considered as key. (and order matters.) * Array-like objects are considered the same as object. * Map and Set object are not treated in a special way here. You should not use this function to compare them. * If one of the arg is not an object, result is same as triple equal operator. URL http://xahlee.info/js/js_test_object_equality.html Created: 2022-10-13 Version: 2026-01-26 */ const xah_is_obj_equal = (xaa, xbb) => { if (xaa === xbb) return true; if ((typeof xaa !== "object") || (typeof xbb !== "object")) return xaa === xbb; const xisArrayA = Array.isArray(xaa); const xisArrayB = Array.isArray(xbb); if (xisArrayA !== xisArrayB) return false; if (xisArrayA && xisArrayB) { if (xaa.length !== xbb.length) return false; else return xaa.every((v1, ii) => xah_is_obj_equal(v1, xbb[ii])); } else { const xkeysA = Object.keys(xaa); const xkeysB = Object.keys(xbb); if (xkeysA.length !== xkeysB.length) return false; return xkeysA.every((kk) => xah_is_obj_equal(xaa[kk], xbb[kk])); } }; // s------------------------------ // test // array with undefined and null console.assert(xah_is_obj_equal([3, null], [3, undefined]) === false); console.assert(xah_is_obj_equal([null], [null])); // array of diff length console.assert(xah_is_obj_equal([3], [3, 4]) === false); // nested array console.assert(xah_is_obj_equal([3, [3, 4]], [3, [3, 4]])); // sparse array console.assert(xah_is_obj_equal([3, , 6], [3, , 6])); console.assert(xah_is_obj_equal([3, undefined, 6], [3, undefined, 6])); // empty array console.assert(xah_is_obj_equal([], [])); // empty object console.assert(xah_is_obj_equal({}, {})); // 2 objects console.assert(xah_is_obj_equal({ 1: 1, 2: 2 }, { 1: 1, 2: 747 }) === false); console.assert(xah_is_obj_equal({ 1: 1, 2: 2 }, { 1: 1 }) === false); console.assert(xah_is_obj_equal({ "a": null }, { "a": null })); // key in different order console.assert(xah_is_obj_equal({ "a": "a", "b": "b" }, { "b": "b", "a": "a" })); // nested objects console.assert( xah_is_obj_equal( { "a": "a", "b": { "a": "a", "b": "b" } }, { "a": "a", "b": { "a": "a", "b": "b" } }, ), ); // arbitrarily nested object/array console.assert( xah_is_obj_equal( { "a": 1, "b": { "a": 1, "b": [3, [{ "a": 1, "b": [3, [3, 4]] }, 4]] } }, { "a": 1, "b": { "a": 1, "b": [3, [{ "a": 1, "b": [3, [3, 4]] }, 4]] } }, ), ); // primitives console.assert(xah_is_obj_equal(3, 3)); console.assert(xah_is_obj_equal(3, 3.0)); console.assert(xah_is_obj_equal("x", "x")); console.assert(xah_is_obj_equal(Infinity, Infinity)); console.assert(xah_is_obj_equal(3, 4) === false); console.assert(xah_is_obj_equal(null, null)); // array-like object console.assert( xah_is_obj_equal( ["a", "b"], (() => { const xx = { 0: "a", 1: "b", length: 2 }; Reflect.defineProperty(xx, "length", { enumerable: false }); return xx; })(), ) === false, "array vs array-like", ); console.assert( xah_is_obj_equal( ["a", "b"], { 0: "a", 1: "b", length: 2 }, ) === false, "array vs array-like but with length as enumerable ", );