The Heap References And The Comparison Problem

Why does comparing two identical objects return false? To understand this, we have to look into the Heap.

April 25, 20263 min read2 / 5

In the last part, we saw how the DOM boundary forces automatic coercion. But coercion isn't just about strings and numbers. When we work with objects, we run into a much deeper problem involving how JavaScript stores data in memory.

The Essentials

  1. Primitives (Value): Stored directly in memory. If you compare 7 === 7, you are comparing the actual numbers.
  2. Objects (Reference): Stored in a larger, more flexible memory store called the Heap.
  3. The Pointer: In JavaScript memory, we don't store the actual object; we store a link (address/pointer) to its position in the heap.

The "False" Comparison

Imagine we are building an authentication feature. We have a userStored object in memory and a userSubmitted object that comes from the user filling out a form.

JavaScript
const userStored = { name: "Will", id: 105 }; const userSubmitted = { name: "Will", id: 105 }; console.log(userStored === userSubmitted); // false

They look exactly the same. They have the same name and the same ID. So why is the result false?

Comparing Pointers, Not Contents

When we use the strict equality operator (===) on two objects, we are not comparing their contents. We are comparing their positions in memory. This is fundamentally different from how primitive memory works.

  • userStored is a link to address 1001 in the heap.
  • userSubmitted is a link to address 1002 in the heap.

When JavaScript asks, "Is address 1001 equal to 1002?" the answer is an absolute no.

JavaScript Execution Engine
Thread of Execution
1const userStored = { name: "Will", id: 105 };
2const userSubmitted = { name: "Will", id: 105 };
3const result = userStored === userSubmitted;

Step 1:In global memory, userStored holds a reference (address 1001) to the object in the heap.

Memory
userStoredref:1001
Call Stack
Global
Bottom of Stack

No Built-in "Deep" Comparison

This means there is no built-in way in JavaScript to compare the contents of two objects. If you want to see if they are the same, you have to manually traverse them (grabbing the properties one by one and comparing them directly).

This "pointer math" or lack thereof is why cloning or backing up objects is also tricky. If you do const backup = userStored, you aren't copying the data; you're just copying the address. Both labels now point to the same object at address 1001.

Why Does This Matter?

This distinction between the heap and the stack is vital for what comes next. We're going to encounter built-in objects (like Date) where we desperately want to compare their contents or even do math on them. But if they are just references to memory positions, how can we ever get under the hood?

In the next part, we'll look at the "Date Puzzle" and how it sets the stage for metaprogramming.

Further Reading and Watching