Check if two values are deeply equal by recursively comparing all nested properties. Works with objects, arrays, and primitives.
Code
Generalconst deepEqual = (x, y) => {
if (x === y) return true;
if (typeof x !== typeof y) return false;
if (typeof x !== 'object' || x === null || y === null) return false;
const keysX = Object.keys(x), keysY = Object.keys(y);
if (keysX.length !== keysY.length) return false;
return keysX.every(k => deepEqual(x[k], y[k]));
};
return deepEqual(a, b);Parameters
First value
Second value
Browser·fetch() may be limited by CORS
Why Not Use ===?
JavaScript's === compares references, not values:
{ a: 1 } === { a: 1 } // false (different objects)
[1, 2] === [1, 2] // false (different arrays)
const obj = { a: 1 };
obj === obj // true (same reference)
Deep equality compares contents:
deepEqual({ a: 1 }, { a: 1 }) // true (same values)
deepEqual([1, 2], [1, 2]) // true (same elements)
Why Not Use JSON.stringify()?
Stringifying works sometimes but has gotchas:
// Works
JSON.stringify({a:1}) === JSON.stringify({a:1}) // true
// FAILS: Key order matters
JSON.stringify({a:1, b:2}) === JSON.stringify({b:2, a:1}) // false!
// FAILS: Can't handle undefined, functions, symbols
JSON.stringify({a: undefined}) // "{}" (undefined stripped)
How The Algorithm Works
- Same reference? → Return true (fast path)
- Different types? → Return false
- Primitives? → Compare with
=== - Objects/Arrays? → Recursively compare all keys
deepEqual({x: {y: 1}}, {x: {y: 1}})
↓
deepEqual({y: 1}, {y: 1})
↓
deepEqual(1, 1)
↓
true
Limitations of This Implementation
| Case | Behavior |
|---|---|
| Circular references | Stack overflow |
| NaN | NaN === NaN is false in JS |
| -0 vs +0 | Treated as equal |
| Dates | Compared as objects, not timestamps |
| RegExp | Compared as objects, not patterns |
| Maps/Sets | Not supported |
Production-Ready Alternatives
For edge cases, use battle-tested libraries:
// Lodash
_.isEqual(obj1, obj2)
// Node.js built-in
require('assert').deepStrictEqual(obj1, obj2)
// Jest/Vitest
expect(obj1).toEqual(obj2)
Common Use Cases
- Unit testing — Assert expected vs actual objects
- React — Check if props changed (shouldComponentUpdate)
- Caching — Determine if cached value is still valid
- Diffing — Detect changes between states
More JavaScript Snippets
Count Object Properties
Count the number of enumerable properties in an object.
Deep Clone Object
Create a deep copy of an object (handles nested objects and arrays).
Deep Freeze Object
Recursively freeze an object and all nested objects to make them immutable.
Deep Merge Objects
Deep merge two objects, combining nested properties.
Flatten Object
Flatten a nested object to a single level with dot notation keys.
Get Nested Value
Safely get a nested property value from an object.