DEV Community

Cover image for Most common confusion about equality in JavaScript
Kadon
Kadon

Posted on

Most common confusion about equality in JavaScript

Hello awesome devs of the internet ๐Ÿ˜€,
In this blog post we shall discuss and learn more about one weird problem faced by JavaScript developers (beginners and some advanced too ๐Ÿ˜…). Below we break down the complexity of equality checks in JavaScript both at the operator level and at the object level.

Equality Checks !

Equality checks is one of those things we all end up doing generally due to the fact that we canโ€™t avoid the famous conditional if - else statement unless we try really hard.

Equality Comparators

The most basic equality comparators are strict equality(===) and loose equality(==) which shall both be reviewed below. Some more complex comparators exist such as Object.is() which we might speak about in another blog if you are interested in.

The difference between == and === often confuse a lot of new JavaScript developers since they look alike and most of the time give us the same result โ€” until it doesnโ€™t.
One of the conveniences in JavaScript is that it will automatically coerce any value being referenced in a boolean context to a boolean value. But there are cases where this can be as confusing as it is convenient.

Briefly,

The Strict Equality, === basically compares two values as is i.e. without any type conversion. If the values youโ€™re comparing are numbers, then they are considered equal if they are the same and not NaN.
This is somehow due to the fact that the === doesnโ€™t know if the compared value has the same type or not.

on the other hand, Loose Equality == converts values into a common type before the comparison is made. as such the equality of the compared objects is determine on the base of their conversion to the same type.

here is what i mean :

with strict equality check

console.log(404 === 404); //true => type and value is same
console.log(404 === '404'); //false => type is not the same
console.log('404' === '404'); //true => type and value is the same
Enter fullscreen mode Exit fullscreen mode

meanwhile with loose equality check,

console.log(404 == 404); //true => both have the same value

console.log(404 == '404'); //true => after conversion, both are equal

console.log('404' == '404'); //true. => No conversion needed but value are similar nevertheless
Enter fullscreen mode Exit fullscreen mode

Some of the following, for example, have been known to bite many JavaScript developers at least once :

// All of these evaluate to 'true'!

console.log(false == '0');
console.log(null == undefined);
console.log(" \t\r\n" == 0);
console.log('' == 0);
Enter fullscreen mode Exit fullscreen mode

As these examples demonstrate, the rules of type coercion can sometimes be easy to visualize. Accordingly, unless type coercion is explicitly desired, itโ€™s typically best to use === and !== (rather than == and !=), so as to avoid any unintended side-effects of type coercion (conversion before equality check ) . (== and != automatically perform type conversion when comparing two things, whereas === and !== do the same comparison without type conversion.)

Let's get deeper

To better understand let's get through many examples of different nature. you will notice that these equality checks might behave in an unexpected way and therefore learn from this, here we go...

1- With objects

let myObject = new String('item');
let myString = 'item';

console.log(myObject == myString );
//returns true. => after conversion, semantically, it's the same.

console.log(myObject === myString );
//returns false. => there is no conversion and type is different despite having the same value.
Enter fullscreen mode Exit fullscreen mode

2- With Binary
Boolean values first converted into to 1 or 0 by ==. therefore :

console.log(true == 1); //returns true 
console.log(true === 1); //returns false => types are different
Enter fullscreen mode Exit fullscreen mode

3-String vs Boolean
Here, the string value gets converted into a numeric value before equality check:

console.log(true == 'true'); 
//returns false => string can't be transformed into a number

console.log(true == '1');
//returns true =>'1' can be converted into a numeric value and 1 equals 1
Enter fullscreen mode Exit fullscreen mode

4-Objects vs boolean
Guess what?, here the object gets converted into a primitive type and if it ends up being a number, then it has a chance of throwing the correct and expected output.

let x = new String('1');
let y = new String('true');

console.log(x == true); //true. x can be converted to a number
console.log(y == true); // false. y can't be converted into a number

//both console logs will return false if === is used because type is different.
Enter fullscreen mode Exit fullscreen mode

Bonus

Since weโ€™re talking about type coercion and comparisons โ€“ itโ€™s worth mentioning that comparing NaN with anything (even NaN!) will always return false. You therefore cannot use the equality operators (==, ===, !=, !==) to determine whether a value is NaN or not. Instead, use the built-in global isNaN() function:

console.log(NaN == NaN);    //return  false
console.log(NaN === NaN);   //return  false
console.log(isNaN(NaN));    //return  true
Enter fullscreen mode Exit fullscreen mode

Conclusion

Hopefully this has cleared up any confusion or mysterious differences between == and ===, and help reduce potential bugs caused by equality operators. Sometimes things look the same but the situation and scenario in which they are use also determine their final outcome.

So a main point to retain from this blog is:

The big difference between strict and loose equality is that the later converts values into a common type before the comparison is made. While === does no conversion at all and performs the comparison as is, == converts the value and determines sameness based on that.

Thanks for your kind attention.

Top comments (0)