JavaScript
Object Comparison
Web Development
Programming
Code Optimization

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.

Practice algorithms

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.

javascript
1const a = { name: "Alice" };
2const b = { name: "Alice" };
3const c = a;
4
5console.log(a === b); // false
6console.log(a === c); // true

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.

javascript
console.log(Object.is(NaN, NaN));   // true
console.log(Object.is(+0, -0));     // false
console.log(Object.is({ x: 1 }, { x: 1 })); // false

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.

javascript
1function shallowEqual(a, b) {
2  const keysA = Object.keys(a);
3  const keysB = Object.keys(b);
4
5  if (keysA.length !== keysB.length) {
6    return false;
7  }
8
9  return keysA.every(key => Object.hasOwn(b, key) && a[key] === b[key]);
10}
11
12console.log(shallowEqual({ x: 1, y: 2 }, { x: 1, y: 2 })); // true
13console.log(shallowEqual({ x: { y: 2 } }, { x: { y: 2 } })); // false

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:

javascript
1import isEqual from "lodash/isEqual.js";
2
3const a = { name: "Alice", details: { age: 25, city: "Paris" } };
4const b = { name: "Alice", details: { age: 25, city: "Paris" } };
5
6console.log(isEqual(a, b)); // true

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:

javascript
JSON.stringify(a) === JSON.stringify(b)

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.stringify as 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

  • '=== and Object.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.stringify comparison 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
Course
Intermediate
27 lessons
15 hours
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 course
Track 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.

Practice algorithms

All Rights Reserved.