Frontend Myths Exposed: Dispelling Common Misconceptions about == in JavaScript

Rafał Opacki
Jit Team
Published in
4 min readMar 25, 2024

--

Introduction

Let’s delve into JavaScript and its mechanisms. For developers, especially those well-versed in other programming languages, JavaScript can appear unfamiliar. Several features behave uniquely compared to other languages, and today, we’ll explore a myth surrounding one of these distinctive features, namely coercion and equality operators.

The Illusion

In various sources, the definition of the “==” operator (commonly referred to as “loose equality” or simply “equality”) is sometimes imprecise. The misconceptions often portray it as disregarding data types, focusing solely on values:

“==” doesn’t care about data types, only about the values

or:

“==” doesn’t check types

As is often the case with myths, there’s a kernel of truth: utilizing the loose equality operator can yield results that appear to disregard types:

2 == "2" // true

While the “===” operator, known as “strict equality”, effectively verifies both the values and types of the operands:

2 === "2" // false

Where could that myth I mentioned earlier be hiding? It appears that the loose equality operator is indeed functioning accurately. However, it’s crucial to note that while the output of loose equality comparisons may give the impression of no type checks being conducted, this notion is misleading. The accuracy lies in the definition of the operation, not just the output it produces.

Separating Fact from Fiction

Both operators, “==” and “===” prioritize data types and perform type checks before executing their respective algorithms. Indeed, it’s accurate that even the “==” operator verifies types before assessing values. That’s the truth.

Referencing the ECMAScript 262 documentation, the JavaScript specification outlines the IsLooselyEqual algorithm [1], responsible for handling the “==” operation. The attached image illustrates a comprehensive process involving 14 steps. Notably, this process heavily involves type checking, as evidenced by the initial step involving Type(x), and introduces coercion as a significant mechanism throughout the operation.

Algorithm responsible for loosely equal type checking

Coercion involves converting the value of one type to another, either explicitly by intentional actions or implicitly through JavaScript mechanisms without any user intervention.

A fascinating observation is that when both types match, the IsStrictlyEqual algorithm (step 1.a) is utilized, the very same algorithm employed for the “===” operator. [2]

Algorithm responsible for strictly equal type checking

Let’s delve into the 5th step of the IsLooselyEqual:

Numer and string comparison algorithm

which is pertinent to our discussion, as per the snippet provided:

2 == "2" // true
// x is a Number (2)
// y is a String ("2")

Here, implicit coercion occurs with the invocation of the ToNumber(y) function. This coercion process transforms the value (y, which is “2”) from its original type (String, in this instance) to a different type (in this case, Number). Before the comparison of values occurs, this step involves both type checking and coercion, aligning both values to the same type (Number), enabling a direct comparison between the two numbers.

2 == "2" // true

//Step 1.
// -> checks both types
// -> both types are different
// -> perform next steps of the IsLooselyEqual

//Step 2.
// -> "2" (String) will become 2 (Number) - Coercion mechanism

//Step 3.
// -> value 2 (number, from the left side) is compared with value 2 (number, on the right side)

In this scenario, the strict equality operator would return false, as depicted in the image provided earlier. Since both types are different, they don’t qualify as strictly the same:

2 === "2" // false

//Step 1.
// -> checks both types
// -> both types are different
// -> end the process, return false

Summary

In summary, both comparison operators check types, yet the loose equality operator (==) takes an extra step. It initially examines the types of the compared values and aligns them to the same type (with implicit coercion) if they differ, then it proceeds with the values comparison. That extra step isn’t involved when using the strict equality operator (===). In instances where the values differ, it straightforwardly returns false. Understanding the nuances between these operators is crucial for writing reliable and accurate JavaScript code.

--

--