JavaScript: == vs === Operator

Introduction

Comparison operators are used in logical statements to determine whether two variables or objects are equal by some already set or custom defined criteria. If the two variables or objects are deduced to be equal the operator returns true, and false if they aren't.

Comparison operators in JavaScript are:

  • < - less than
  • > - greater than
  • <= - less or equal than
  • >= - greater or equal than
  • == and === - equal to (loose and strict equality operator)
  • != and !== - not equal to (loose and strict inequality operator)

JavaScript is interesting because it's got two visually very similar, but in practice very different comparison operators for equality: == and ===.

In this article, we will explain the differences between loose and strict equality operators and go over some examples of their usage.

Loose Equality Operator in JavaScript (==)

Double equals in JavaScript are testing for loose equality. This permits the JavaScript engine to try and cast these expressions to a common type. Meaning that the expressions don't necessarily need to be of the same type.

The process of converting a value from one type to another is called type coercion. Type coercion can be explicit and implicit.

Explicit type coercion is, as its name implies, done explicitly in code by a programmer, using the built-in methods that JavaScript provides (Number(), String(), Boolean()...).

For example:

// This would result in x being a number 42
let x = Number("42");

// Similarly,this would result in y being cast to the boolean value false 
let y = Boolean(0);

Implicit type coercion is, on the other hand, done implicitly by JavaScript. This coercion type is usually done when we use operators on different types, but can be reasonably "matched" by one of them, for example:

// x is going to be cast to the string "1".
let x = 1 + ""; 

To explain this example, let's look at it from a JavaScript engine's perspective:

The expression should be evaluated and assigned to x. The first number is 1 and has + operator besides it. This implies integer addition with the next number. However, there's an empty string, "", there. This can't be converted into a number. However, we can also concatenate strings with +, so let's match them as strings and perform concatenation. Finally, the result is returned and assigned to x.

To sum up, the JavaScript engine tries to convert both values to a type that supports
the + operator, which in this case is a string.

/* In this case, the JS engine deduces that both the operands and the result have to be cast to an integer because it's the only type that has a defined subtraction operation (-) */

let y = "5" - "2";

// Because booleans don't have a + operation, the JS engine converts both true values into 1's

let z = true + true;

Now, it's exactly this type of coercion that the == operator uses to check for equality. Let's go over some examples of loose equality operator usage, in the Node REPL:

> 42 == "42"
true
> "42" == '42'
true

42, "42" and '42' are all matched into the same data type, and are all loosly equal, returning true in the comparisons.

Booleans follow the same principle:

> true == 1
true
> true + true == 2
true
> false == 0
true
> false + true == 1
true

true is 1 and false is 0. We can implicitly convert these into integers by adding them.

Finally, here's an example of an (unreadable) but syntaxically valid comparison:

> ("42" == '42') + (42 == "42") == 2
true

"42" == '42' is evaluated as true, as well as 42 == "42". This side of the expression therefore also evaluated to true + true, which is implicitly converted into 1+1. That's obviously == to 2, so the expression returns true.

Falsy Value Comparison in JavaScript

A falsy value is a variable which evaluates to false. In JavaScript, there are seven falsy values - false, 0, "", [], null, undefined, NaN.

There are a couple of simple rules when it comes to using the double equals operator on falsy values:

  • false, 0 and "" are equivalent
  • undefined and null return true when compared to themselves or each other, and false when compared to anything else
  • NaN compared to anything (even another NaN) returns false

So, these would all be true:

> false == 0;
true
> false == "";
true
> 0 == "";
true
> undefined == null;
true
> undefined == undefined;
true
> null == null;
true
> [] == false;
true
> [] == 0;
true

While these would all be false:

> undefined == false;
false
> 0 == null;
false
> null == true
false
> NaN == false;
false
> NaN == NaN;
false

Strict Equality Operator in JavaScript (===)

Triple equals in JavaScript stands for strict equality. This means that, unlike the loose equality operator we talked about before, there is no implicit conversion. Meaning the output won't be true unless both the type and values of the two expressions match. They aren't matched on type anymore.

Now, let's have a look at some strict equality operator examples:

> true === true
true
> true === 1
false
> false === 0
false

This example produces true in the first case because both the type (boolean) and value (true) are equal. In the other two cases, it returns false, because although the values are the same, the types don't match. We're comparing a boolean to an integer.

> 42 === 42
true
> 42 === "42"
false

Here, both the number and value are equal in the first example, resulting in true, while the value and type mismatch in the second example, resulting in false.

Conclusion

In this article we explained the difference between the loose equality operator and the strict equality operator in JavaScript.
We also explained what type coercion was, and the concept of explicit and implicit type coercion.

You may have noticed that implicit type coercion that occurs when we use the loose equality operator in JavaScript can be pretty unpredictable an counter-intuitive. This is why, if you're not very experienced with JavaScript, it is usually better to stick to the strict equality operator when checking whether or not the two expressions are equal.

By using the strict equality operator you are testing both the type and value, and you can therefore be sure to always execute a true equality test.

Author image
About Mila Lukic