Object comparison in JavaScript
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
Object comparison in JavaScript depends entirely on what you mean by "equal". Native operators compare object identity, not object content. If you want shallow equality or deep structural equality, you have to say so explicitly.
=== Compares References for Objects
Two different object literals are not equal under ===, even if they contain the same data.
That is because objects are reference values. === answers "are these the same object?" not "do these objects have the same contents?"
Object.is() Is Still Reference Comparison for Objects
Object.is() changes behavior for a few primitive edge cases such as NaN and signed zero, but it does not magically become deep object comparison.
So for objects, Object.is() is still about identity, not structure.
Shallow Equality Is Useful for Flat Data
If you only need to compare top-level properties, a shallow comparison is often enough.
That last case fails because the nested objects are different references. That is exactly what "shallow" means.
Deep Equality Is a Different Problem
If nested structures matter, you need a deep comparison strategy.
One practical option is to use a library function such as Lodash isEqual:
Deep equality is more expensive and more nuanced, especially once arrays, dates, maps, sets, and custom prototypes enter the picture.
Be Careful with JSON.stringify
People often use:
This can work for simple JSON-like data, but it is not a general deep-equality solution. It can fail or mislead when:
- property order differs
- values include
undefined - objects contain functions, dates, maps, or sets
- circular references are present
So treat it as a narrow convenience, not as a universal comparison technique.
Pick the Comparison That Matches the Use Case
A good rule:
- use
===when identity matters - use shallow comparison for flat configuration or props-style checks
- use deep comparison only when structural equivalence really matters
That choice matters for correctness and performance. Many bugs come from using a deep comparison where identity was intended, or from using identity when structure was intended.
Common Pitfalls
- Expecting
===to compare object contents. - Assuming
Object.is()performs deep comparison for objects. - Using shallow comparison on nested structures and getting false negatives.
- Relying on
JSON.stringifyas if it were a universal deep-equality tool. - Doing expensive deep comparisons in hot paths without questioning whether identity or shallow equality would be enough.
Summary
- '
===andObject.is()compare object identity, not object structure.' - Use shallow comparison when only top-level properties matter.
- Use deep comparison only when nested structural equality is actually required.
- '
JSON.stringifycomparison is limited and should not be treated as a general solution.' - Always choose the comparison rule that matches the semantics you actually care about.
Related reading
- Objective-C ARC strong vs retain and weak vs assign
- Objective-C Where to remove observer for NSNotification?
- Objective C - Assign, Copy, Retain
- Octave logistic regression difference between fmincg and fminunc
- Object is enumerable but not indexable?
- offsetting an html anchor to adjust for fixed header
- Octave logistic regression difference between fmincg and fminunc
- oh-my-zsh slow, but only for certain Git repo

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.