Last updated: September 27, 2022.
If either operator judges two bits of data to be equal, the comparison will return the Boolean value true and otherwise false.
For most comparisons you make, both the loose and strictly equality operators return the same Boolean value:
/*** Basic comparisons using the loose and strict equality operators ***/ 2 == 2; // Returns true 2 === 2; // Returns true 2 == 4; // Returns false 2 === 4, // Returns false "a" == "a"; // Returns true "a" === "a"; // Returns true
Loose equality tests for equality of value only
The loose equality operator compares value only. It ignores data type. So a comparison between a numeric and string value, for example, can return true if the values are the same!
/*** Loose equality check ignores data type ***/ 2 == "2"; // returns true
It achieves this by silently coercing both bits of data to the same type, so they can be compared. In the above example,
2 == "2" returns a predictable result.
But coercion can also lead to some unexpected results:
/*** Coercion can generate unexpected results ***/ console.log(0 == false); // true console.log("" == false); // true console.log(null == false); // false console.log(null == undefined); // true
It is not easy to keep track of all the unexpected results generated by the loose equality operator coercion the two types under comparison.
Even if you are familiar with truthy and falsy values, this will not help you! In the example above, only falsy values are compared with each other. But the return values are mixed. Thus, you cannot rely upon your knowledge of truthy and falsy values to know what result the coercion will produce.
Strict equality test for equality of value and type
The strict equality operator is much more predictable, which can help to avoid unforeseen errors.
For example, if we make the same comparisons as we did with the loose equality operator, you can see a much more consistent behavior:
/*** Strict equality generates more predictable outcomes ***/ console.log(2 === "2"); // false console.log(0 === false); // false console.log("" === false); // false console.log(null === false); // false console.log(null === undefined); // false
The strict equality operator will only return true if the value and data type are the same. So, a comparison between a numeric and string value with never return true.
/*** Strict equality will only return true if there is equality of value AND type ***/ console.log(null === undefined); // false console.log(undefined === undefined); // true console.log(null === null ); // true console.log(2 === "2"); // false console.log("2" === "2"); // true console.log(2 === 2); // true
So which should you use?
There are in fact some differences of opinion.
Why always use the strict equality operator?
The short answer: the strict equality operator is more predictable, helping you avoid unexpected outcomes and errors.
But taking advantage of the flexibility of the loose equality operator can be tempting.
Though we recommend always using the strict equality operator, there are two common exceptions to this rule that you will find in many existing code bases.
Let’s look at these now – and why, even in these cases, it is better practice to test for strictly equality.
Common exception #1: Testing for null or undefined
One way that you can take advantage of the flexibility of the loose equality operator is to test if a value is either null or undefined by placing either null or undefined on one side of the equality test. If the other value is either null or defined, true will be returned and false otherwise.
/*** null and undefined only return true against each other in loose equality ***/ console.log(false == null); // false console.log(0 == null); // false console.log("" == null); // false console.log(NaN == null); // false console.log(undefined == null); // true
This solution is perfectly functional. However, given that one side of an equality test is usually dynamically inserted, someone looking at your code may wonder if you are checking for undefined only or are purposely taking advantage of the loose equality operator’s flexibility.
If you are testing for both null or undefined, a more unambiguous solution is to state that in your code explicitly:
/*** A more explicit alternative to test for null and undefined ***/ console.log(undefined || null === null); // true
Now, anyone looking at your code will be in no doubt that you are testing for null or undefined on the right-hand side.
Common exception #2: Intentionally ignoring type
It can be tempting to use the loose equality operator to deliberately ignore data type.
For example, imagine that you are aware that the incoming data will a number value in a string, and you want to check if it is equal to 0. You can use the loose equality operator to ignore type:
/*** "0" and 0 are the same in loose equality ***/ console.log("0" == 0); // true
In this comparison, it works as expected. But if “0” is replaced by something else (as is often the case when working with data dynamically), the comparison can throw up some strange results
/*** "0" is the also same as false and NaN in loose equality ***/ console.log("0" == false); // true console.log("0" == NaN); // true
To avoid this, use the in-built parseInt method available on the Number object to convert the string to a number. If you then try the same comparisons, only the comparison between “0” and numeric 0 will return true.
/*** Using parseInt and strict equality achieves the same outcome while avoiding unexpected outcomes ***/ console.log(Number.parseInt("0") === 0); // true console.log(Number.parseInt("0") === false); // false console.log(Number.parseInt("0") === NaN); // false
The loose equality operator tests for a difference in value only and ignores type. It achieves the by silently coercing the values being compared to be of the same type. The strict equality operator, on the other hand, returns true only if value and type match.
Because it does not coerce values, the strict equality operator returns much more predictable results. If you want to avoid unexpected errors, it is best to always use the strict equality operator.
But it is also good to know the common exceptions to the use of the strict equality operator, because this strategic use of the loose equality operator is commonplace in existing code bases.