JS: Test Equality of Array and Object by Content 📜

By Xah Lee. Date: . Last updated: .

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 argument is not object type, 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]) === true);

// 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]]) === true);

// sparse array
console.assert(xah_is_obj_equal([3, , 6], [3, , 6]) === true);
console.assert(xah_is_obj_equal([3, undefined, 6], [3, undefined, 6]) === true);

// empty array
console.assert(xah_is_obj_equal([], []) === true);

// empty object
console.assert(xah_is_obj_equal({}, {}) === true);

// 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 }) === true);

// key in different order
console.assert(xah_is_obj_equal({ "a": "a", "b": "b" }, { "b": "b", "a": "a" }) === true);

// nested objects
console.assert(
 xah_is_obj_equal(
  { "a": "a", "b": { "a": "a", "b": "b" } },
  { "a": "a", "b": { "a": "a", "b": "b" } },
 ) === true,
);

// 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]] } },
 ) === true,
);

// primitives
console.assert(xah_is_obj_equal(3, 3) === true);
console.assert(xah_is_obj_equal(3, 3.0) === true);
console.assert(xah_is_obj_equal("x", "x") === true);
console.assert(xah_is_obj_equal(Infinity, Infinity) === true);
console.assert(xah_is_obj_equal(3, 4) === false);
console.assert(xah_is_obj_equal(null, null) === true);

// 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 "
);

Test Object Equality by JSON String, Ordering Problem

JavaScript. Object and Inheritance

JavaScript. Boolean

JavaScript. Test Equality