Equality in JavaScript

JavaScript's use of equality is, objectively, counterintuitive. But there is some method to the madness. In its own way, it makes sense (mostly). But it can not be inferred. You have to learn it.

Type coercion with ==

The thing that everyone hates. So what is type coercion? Type coercion is what happens when you ask JavaScript to compare something that is sort-of-kind-of might be true. The list of rules are massive. Numbers can turn into strings; null turns into 0; booleans convert to numbers; This monstrosity of "logic" with null and 0. You can sit down and learn all of the rules if you hate yourself. But the more convenient option is to just never use ==

Strict equality with ===

This is equality with zero type coercion. Much better.

JavaScript's strict equality properly compares primitives

For primitives, comparisons are very straightforward. They are compared by its value, because that's all a primitive has.

Equality by value comparison breaks down for any type of object

Sounds weird, but it makes sense (I promise).

  [] === [] //false
[] instanceof Object // true
new String("") === new String("") //false
new String("") instanceof Object //true
'' === '' // true
'' instanceof Object // false

For objects, anything that's not a primitive, JavaScript's equality operator can only compare whether or not objects have the same identity. Not if they have the same value. JavaScript checks if the two objects exist in the same memory address (aka they are the exact same). This is formally known as identity comparison. JavaScript is not the only language that does equality by reference, so it's unfair to hold it against the language.

  a = [] // empty array in one memory address
b = [] // another empty array in another memory address
a === a //true, same array in memory
a === b //false, not same array in memory
a === [] //false, new array instantiated that is obviously not the same as a

Testing equality of NaN: an entire paragraph dedicated to it

NaN is tricky. Strangely enough, NaN is not equal to itself when using the equality operators. Which is why isNaN exists, but isNaN has an unintuitive exception: the fact that isNaN(undefined) === true. ES6 to the rescue: Number.isNaN (yes they are different). No exceptions. There are some wild algorithms that existed to test true NaN equality with no exceptions, but now it's much simpler:

  const equalityTestNaN = (num1, num2) => {
  return Number.isNaN(num1) && Number.isNaN(num2)
}

If both arguments are NaN, then they're equal to each other by proxy, right? Another nice way to check equality would be to use Object.is. No algorithm required. Just remember that this comparator tests for any type.

  Object.is(NaN, NaN) //true

Comments

Popular posts from this blog

Contrasting var and ES6s new declarations: let and const

Modularity vs. Abstraction. Which is More Important?

Unit testable components pt.3: Testing components