Deep equality check
Compare two values structurally, including nested objects, arrays, Dates, Maps and Sets.
- JavaScript
- GreenSnippets
- MIT
- Executed with Node.js 22
function deepEqual(a, b) {
if (Object.is(a, b)) return true;
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 Map || a instanceof Set) {
if (a.size !== b.size) return false;
const left = [...a];
const right = [...b];
return left.every((entry, i) => deepEqual(entry, right[i]));
}
const keysA = Object.keys(a);
if (keysA.length !== Object.keys(b).length) return false;
return keysA.every((key) => Object.hasOwn(b, key) && deepEqual(a[key], b[key]));
}Example / expected output
deepEqual({ a: [1, { b: 2 }] }, { a: [1, { b: 2 }] }) // trueHow it works
=== compares references. This recursive check treats NaN as equal to itself, compares Dates by time, and Maps and Sets by their entries in order. It does not handle circular structures; on the server, isDeepStrictEqual from node:util covers those.
Related snippets
- TypeScript Tested
Typed Object.keys and Object.entries
Helpers that keep key types instead of widening to string, for objects you know the shape of.
- JavaScript Tested
Pick and omit object keys
Build a new object with only some keys, or without some keys, without mutating the original.
- JavaScript Tested
Deep merge plain objects
Recursively merge configuration objects without mutating the inputs and without prototype pollution.
- JavaScript Tested
Deep clone an object with structuredClone
Copy nested objects, arrays, Maps, Sets and Dates without sharing references, using the built-in structuredClone.

