JavaScript
Object comparison
Web development
Programming tutorial
Equality test

How can I determine equality for two JavaScript objects?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Object equality in JavaScript is tricky because the language distinguishes between reference identity and structural equality. Two objects can contain the same data and still compare as unequal with === because they are different objects in memory.

Reference Equality Comes First

For objects, === checks whether both variables point to the exact same object.

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

That behavior is correct and important. It answers "are these the same object?" not "do these objects contain the same values?"

Shallow Equality

If you only care about top-level properties, a shallow comparison is often enough.

javascript
1function shallowEqual(left, right) {
2  if (left === right) return true;
3  if (!left || !right) return false;
4
5  const leftKeys = Object.keys(left);
6  const rightKeys = Object.keys(right);
7
8  if (leftKeys.length !== rightKeys.length) return false;
9
10  for (const key of leftKeys) {
11    if (!Object.prototype.hasOwnProperty.call(right, key)) return false;
12    if (left[key] !== right[key]) return false;
13  }
14
15  return true;
16}
17
18console.log(shallowEqual({ x: 1 }, { x: 1 })); // true
19console.log(shallowEqual({ x: { y: 2 } }, { x: { y: 2 } })); // false

This is useful in some UI optimization paths, but nested objects still compare by reference.

Deep Equality

When nested arrays and objects matter, you need a recursive comparison.

javascript
1function deepEqual(left, right) {
2  if (left === right) return true;
3  if (typeof left !== typeof right) return false;
4  if (left === null || right === null) return left === right;
5
6  if (typeof left !== "object") return left === right;
7
8  const leftKeys = Object.keys(left);
9  const rightKeys = Object.keys(right);
10
11  if (leftKeys.length !== rightKeys.length) return false;
12
13  for (const key of leftKeys) {
14    if (!Object.prototype.hasOwnProperty.call(right, key)) return false;
15    if (!deepEqual(left[key], right[key])) return false;
16  }
17
18  return true;
19}
20
21console.log(
22  deepEqual(
23    { user: { name: "Ada" }, roles: ["admin", "editor"] },
24    { user: { name: "Ada" }, roles: ["admin", "editor"] }
25  )
26); // true

That gets you much closer to semantic equality, though fully correct deep equality across every JavaScript type is more involved than a short helper suggests.

Why JSON.stringify Is Not a General Solution

Many developers try this shortcut:

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

It can work for simple plain objects, but it has important limits:

  • Property order can affect the result
  • 'undefined, functions, and symbols are not represented normally'
  • Dates, maps, sets, and custom prototypes are not compared meaningfully
  • Circular references throw errors

So JSON.stringify is fine for controlled data shapes, but it is not a robust equality strategy for general objects.

Libraries Are Often the Practical Choice

If you need production-grade deep equality, a well-tested library is often better than maintaining your own edge cases.

javascript
1import isEqual from "lodash/isEqual.js";
2
3const left = { id: 1, tags: ["a", "b"] };
4const right = { id: 1, tags: ["a", "b"] };
5
6console.log(isEqual(left, right)); // true

That is especially helpful when your data includes arrays, dates, nested structures, or values that need careful comparison semantics.

Pick the Equality Rule That Matches the Problem

The right comparison depends on what you are trying to prove:

  • Reference identity for cache keys, mutation tracking, or React dependency behavior
  • Shallow equality for lightweight prop checks
  • Deep equality for data validation, testing, or state comparison

There is no single "object equality" rule that is correct for every application.

Common Pitfalls

The biggest mistake is expecting === to compare object contents. For objects, it only compares references.

Another issue is using JSON.stringify as a universal deep-equality check. It silently fails as a general rule once values become more complex than plain JSON-safe objects.

Developers also write quick recursive comparators and forget edge cases such as arrays, null handling, dates, or circular references.

Finally, deep equality can be expensive. If you are calling it on large objects in performance-sensitive UI code, make sure the extra work is actually justified.

Summary

  • '=== checks object identity, not structural equality.'
  • Use shallow comparison only when top-level properties are enough.
  • Use deep comparison for nested objects and arrays.
  • 'JSON.stringify works only for limited, controlled data shapes.'
  • For production-grade deep equality, a tested library is often the most reliable choice.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.