Featured image of post Just JavaScript_06: Equality of Values

Just JavaScript_06: Equality of Values

Kinds of Equality

In JavaScript, there are several kinds of equality. If you’ve been writing JavaScript for a while, you’re probably familiar with at least two of them:

  • Same Value Equality: Object.is(a, b).
  • Strict Equality: a === b (triple equals).
  • Loose Equality: a == b (double equals).

Most tutorials don’t mention the Same Value Equality at all. We’ll take a road less traveled, and explain it first. We can then use it to explain the other kinds.

Same Value Equality: Object.is(a, b)

In JavaScript, Object.is(a, b) tells us if a and b are the same value:

1
2
console.log(Object.is(2, 2)); // true
console.log(Object.is({}, {})); // false

This is called Same Value Equality.

What does “same value” means, exactly, in our mental model? You might already know this intuitively, but let’s verify your understanding.

Check Your Intuition

Consider this example from the Counting the Values exercises:

1
2
3
let dwarves = 7;
let continents = '7';
let worldWonders = 3 + 4;

As a reminder, our sketch for this snippet looked like this:

Now try to answer these questions using the diagram above:

1
2
3
console.log(Object.is(dwarves, continents)); // false
console.log(Object.is(continents, worldWonders)); // false
console.log(Object.is(worldWonders, dwarves)); // true

If two values are represented by a single shape on our diagram, it means that they aren’t really two different values. They are the same one value! And that is the case for which Object.is(a, b) returns true.

In the previous module, we “counted” the values. But really, we were learning about what makes values distinct from one another. And as a result, we also learned the opposite — what it means for values to be the same.

But What About Objects?

By this point, you might be worried about objects. You might have heard that equality doesn’t work with objects, or that it compares “references”. If you have existing intuitions like these, set them aside completely for a moment.

Instead, look at this code snippet:

1
2
3
4
let banana = {};
let cherry = banana;
let chocolate = cherry;
cherry = {};

Remember that {} always means create a new object value. Also remember that = means connect the left side’s wire to the value on the right side.

1
2
3
console.log(Object.is(banana, cherry)); // false
console.log(Object.is(cherry, chocolate)); // ? false
console.log(Object.is(chocolate, banana)); // ? true

Strict Equality: a === b

You have probably used the Strict Equality operator before:

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

There is also a corresponding opposite !== operator.

Same Value Equality vs Strict Equality

So what’s the difference between Object.is and ===?

Same Value EqualityObject.is(a, b) — has a direct meaning in our mental model. It corresponds to the idea of “the same value” in our universe.

In almost all cases, the same intuition works for Strict Value Equ aliy too. For example, 2 === 2 is true because 2 always “summons” the same value:

a === b behaves the same way as Object.is(a, b). However, there are two rare cases where the behavior of === is different.


First Special Case: NaN

Remember that NaN === NaN is always false:

1
console.log(width === height); // false

However, NaN is the same value as NaN:

1
console.log(Object.is(width, height)); // true

The reason for NaN === NaN being false is largely historical so I suggest to acccept it as a fact of life.

所以,不要這樣寫!!!

1
2
3
4
5
6
7
function resizeImage(size) {
  if (size === NaN) {
    // Doesn't work: the check is always false!
    console.log('Something is wrong.');
  }
  // ...
}

這樣檢查是否爲 NaN:

  • Number.isNaN(size)
  • Object.is(size, NaN)

Second Special Case: -0

In regular math, there is no such concept as “minus zero”, but it exists in floating point math for practical reasons. Here’s an interesting fact about it.

Both 0 === -0 and -0 === 0 are always true:

1
2
3
let width = 0; // 0
let height = -width; // -0
console.log(width === height); // true

However, 0 is a different value from -0:

1
console.log(Object.is(width, height)); // false

以上兩個特殊狀況不是很常見。They’re not very common. Now that you know that they exist, you will recognize them in practice. And in most cases, our intuition about what “same value” means is useful for both Object.is(a, b) and a === b.

絕對不要使用 Loose Equality ==

觀念小測驗

JJS: Equality of Values

最後更新 Mar 09, 2024 21:12 +0800