Just JavaScript· 06
Chapter 06 · Counting & Equality

Equality of
Values

Without a clear model of equality, every day is a masked carnival — you can't tell if you're talking to the same value twice or to two different ones. Good news: we already did the hard part by counting. Equality falls right out of it. Same shape on the diagram means the same value.

Lab · the equality comparator

Pick two values. Watch the three equalities decide

Click a slot, then click a value to fill it. The diagram shows whether the two land on the same shape. The three operators report their verdicts — and the rare cases where === disagrees with same-value light up the explanation.

a7
b7
Object.is(a, b)true
a === btrue
a == btrue
01

Three kinds of equality

JavaScript has several equalities. We'll explain the least-known one first, because it maps directly onto our mental model — then use it to explain the rest.

  • Same-value equalityObject.is(a, b)
  • Strict equalitya === b (and its opposite !==)
  • Loose equalitya == b (usually avoided)
console.log(Object.is(2, 2));   // true
console.log(Object.is({}, {})); // false
02

Same value = same shape

Object.is(a, b) is true exactly when a and b point at the same shape on our diagram — the same single value.

Recall the counting sketch:

let dwarves = 7;
let continents = '7';
let worldWonders = 3 + 4;
  • Object.is(dwarves, continents)false — number 7 and string '7' are different values.
  • Object.is(continents, worldWonders)false — different values again.
  • Object.is(worldWonders, dwarves)true3 + 4 summons the same 7 as dwarves.

Objects need no extra concept. {} always creates a new value, so two separately-written {} are two shapes — never equal. It all falls straight out of the model. Try it in the lab above with the two {} chips.

The rule

On our diagram, the same value can't appear twice. Object.is(a, b) is true precisely when a and b sit on the same shape.

03

Strict equality, and its two exceptions

In practice you'll use === most. It matches Object.is in almost every case — with two irregular verbs to memorise.

console.log(2 === 2);   // true
console.log({} === {}); // false

Exception 1 · NaN

NaN === NaN is false, even though they're the same value. So this check never fires:

function resizeImage(size) {
  if (size === NaN) { // always false — broken!
    console.log('Something is wrong.');
  }
}

Three ways that actually detect NaN (all work):

Number.isNaN(size)
Object.is(size, NaN)
size !== size // NaN is the only value not equal to itself

That last one is the punchline of the whole chapter — sit with it.

Exception 2 · negative zero

0 === -0 and -0 === 0 are both true, yet they are different values:

let width = 0;
let height = -width; // -0
console.log(width === height);        // true
console.log(Object.is(width, height)); // false
Don't panic

These are uncommon — Dan reports never hitting the -0 case in his whole career. Just know they exist so you recognise them. For everything else, "same value" intuition serves both Object.is and ===.

04

Loose equality: the bogeyman

== coerces its operands by arcane rules. It's widely considered an early design mistake. Don't memorise it.

console.log([[]] == '');  // true
console.log(true == [1]); // true
console.log(false == [0]);// true

Wait, what?! Many style guides ban == outright. We won't cover its rules — they don't enrich the mental model and you'll want that memory for other topics. Try '7' against 7 in the lab: === says false, but == coerces them to true. That gap is the argument against it in one click.

One == usage is common and worth knowing:

if (x == null) { /* ... */ }
// equivalent to:
if (x === null || x === undefined) { /* ... */ }

Even that can be controversial — agree as a team how much == you tolerate.

05

Recap

  • Same-valueObject.is(a, b) matches "same shape on the diagram". The same value can't appear twice.
  • Strict=== is what you'll use. It equals Object.is except: NaN === NaN is false, and 0 === -0 is true.
  • Detect NaN with Number.isNaN(x) — or the elegant x !== x.
  • Loose== is arcane and usually avoided; the one handy case is x == null.

Why is size !== size a NaN test? Because NaN === NaN is false, so NaN !== NaN is true — and NaN is the only value not equal to itself. Ensuring that test would work was one of the original reasons NaN === NaN was made false, decided before JavaScript even existed.