Most common confusion about equality in JavaScript
Tags: javascript, productivity, codequality
Published: 2020-06-11 18:34:19

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

```javascript
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
```

####meanwhile with loose equality check,
```javascript
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
```
Some of the following, for example, have been known to bite many JavaScript developers at least once :

```javascript
// All of these evaluate to 'true'!

console.log(false == '0');
console.log(null == undefined);
console.log(" \t\r\n" == 0);
console.log('' == 0);
```

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

```javascript
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.
```

2- With Binary
Boolean values first converted into to 1 or 0 by `==`. therefore :
```javascript
console.log(true == 1); //returns true 
console.log(true === 1); //returns false => types are different
```

3-String vs Boolean
Here, the string value gets converted into a numeric value before equality check:
```javascript
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
```

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.

```javascript
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.
```

#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:


```javascript
console.log(NaN == NaN);    //return  false
console.log(NaN === NaN);   //return  false
console.log(isNaN(NaN));    //return  true
```

#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.