$ snippet deep-equal
Deep equality check
Compare two values structurally — nested objects, arrays, Dates, Maps, Sets, NaN — the way you wish === worked.
function deepEqual(a, b) {
if (Object.is(a, b)) return true; // handles NaN, avoids +0/-0 confusion
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) return false;
if (Object.getPrototypeOf(a) !== Object.getPrototypeOf(b)) return false;
if (a instanceof Date) return a.getTime() === b.getTime();
if (a instanceof RegExp) return a.source === b.source && a.flags === b.flags;
if (a instanceof Map) {
if (a.size !== b.size) return false;
for (const [k, v] of a) if (!b.has(k) || !deepEqual(v, b.get(k))) return false;
return true;
}
if (a instanceof Set) {
if (a.size !== b.size) return false;
for (const v of a) if (!b.has(v)) return false; // Set members compared by identity
return true;
}
if (ArrayBuffer.isView(a)) {
if (a.length !== b.length) return false;
for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
return true;
}
const keysA = Reflect.ownKeys(a), keysB = Reflect.ownKeys(b);
if (keysA.length !== keysB.length) return false;
for (const k of keysA) {
if (!Object.prototype.hasOwnProperty.call(b, k)) return false;
if (!deepEqual(a[k], b[k])) return false;
}
return true;
}How it works
The JSON.stringify(a) === JSON.stringify(b) trick fails on key order, undefined, Dates vs strings, and anything JSON can't represent. This version compares primitives with Object.is, special-cases the built-in container types, then compares own keys recursively — arrays fall out of the same logic because their indices are own keys and their length differs if sizes differ.
Gotchas
- Two objects with different prototypes (a class instance and a plain object with the same fields) are not equal here. Drop the prototype check if you want structural-only comparison.
- Circular references cause infinite recursion. Track visited pairs in a
WeakMapif your data can contain cycles. - For React memoization, deep equality on every render can cost more than the re-render it prevents; prefer stable references or shallow comparison.
Ad slot