deepEqual(a, b) checks structural equality — same shape, same values, not the same reference. The interviewer tests whether you handle NaN, +0/-0, null vs {}, and arrays vs objects correctly.
Related deep-dive: Data #1 — Deep Clone & Deep Compare
What is deepEqual()?
deepEqual(a, b) performs structural comparison — it checks whether two values have the same shape and contents, regardless of whether they're the same object in memory. Unlike === (which compares references for objects), deepEqual recursively descends into nested structures and compares every leaf value.
This is the comparison counterpart to deepClone: one creates independent copies, the other verifies they're semantically identical. Both walk the same tree with the same recursion pattern.
The JavaScript-specific edge cases make this more nuanced than it looks:
NaN—NaN === NaNisfalse(the only value not equal to itself). You need a special check: twoNaNvalues are structurally equal.+0and-0—+0 === -0istrue, but1 / +0 !== 1 / -0(Infinity vs -Infinity). Most implementations treat them as equal.typeof null === "object"— comparingnullto{}must returnfalse, not throw from trying to recurse intonull.- Arrays vs objects —
[]and{}have the sametypeof, but one should compare by index and the other by key set.
Real-world use cases:
- Should component re-render? — compare previous and next props/state deeply
- Test assertions —
expect(result).toEqual(expected)in Jest is deep equality - Change detection — diff two config objects or API responses to find what changed
- Caching — check if a cached result is still valid by comparing the input to the original
The interview tests recursion fundamentals plus two or three "did you know about this JavaScript quirk?" moments. Handling NaN, null, and array-vs-object branching cleanly is what separates a passing answer from a thorough one.
The Problem
"Implement deepEqual(a, b) that returns true if a and b have the same structure and values, and false otherwise. It should work for primitives, arrays, and plain objects."
Thought Process
The algorithm has ordered checks:
- Reference equality — if
a === b, returntrue(fast exit). But watch:NaN !== NaNand+0 === -0. - Type mismatch — if
typeof a !== typeof b, returnfalse. - NaN handling —
NaNis the only value wherex !== x. If both areNaN, they're equal. nullcheck — if either isnull, they must be reference-equal (already handled by step 1).- Primitive — return
a === b. - Array — compare lengths, then recurse element-wise.
- Object — compare key counts, then recurse value-wise.
Step 1 — Primitives with NaN
Loading editor...
Step 2 — Arrays
Loading editor...
Step 3 — Objects
Loading editor...
Step 4 — Edge Cases
NaN: deepEqual(NaN, NaN) must return true. Handled by the isNaN check.
+0 vs -0: Object.is(+0, -0) returns false, but +0 === -0 returns true. Our a === b early return treats them as equal. If the interviewer wants Object.is semantics, use Object.is instead of ===.
null vs {}: typeof null === 'object' and typeof {} === 'object'. Our null check before the typeof branch handles this.
Arrays vs objects: deepEqual([], {}) should return false. The Array.isArray(a) !== Array.isArray(b) check handles this.
Prototype properties: Object.keys only returns own enumerable properties, so inherited properties are ignored — which is correct for structural equality.
Full Solution
Loading editor...
What Interviewers Are Testing
- NaN equality — knowing that
NaN !== NaNand handling it explicitly - null vs object — knowing that
typeof null === 'object'and guarding for it - Array vs object distinction — using
Array.isArraybefore falling into the object branch - Short-circuit on reference equality — the fastest check, done first
Complexity
| Time | Space | |
|---|---|---|
| deepEqual | O(N) — each value visited once | O(D) — call stack, D = max depth |
Interview Tips
- Handle NaN first — "Since
NaN !== NaN, I'll check if both values are NaN before anything else." This immediately tells the interviewer you know the quirk. - Check types before recursing — if types differ, return
falseimmediately. Saves work and avoids comparing an array to an object. - State whether you want
===orObject.issemantics for +0/-0 — most interviewers are fine with===, but asking shows awareness. - Mention
hasOwnProperty— checking it prevents inherited properties from affecting equality.