Why NaN === NaN returns false in JavaScript ?!
Tags: javascript, tutorial, programming, node
Published: 2021-08-04 01:01:06

When people start exploring topics about JavaScript they get to feel a little weird sometimes and they also start to wonder why the heck do JavaScript act in such a manner, there have been even Github Repos like [You Don't Know JS](https://github.com/getify/You-Dont-Know-JS) that explains how JavaScript works and so.

Today I wanted to explain a gotcha topic that people usually post memes about and hate on JavaScript because of such a topic ( Which I kinda understand why they do so ), I will be explaining why `NaN === NaN` results in a **Falsy** expression. Let us get started with some basics first.

## What is the difference between `==` and `===`

Whenever we compare two variables using the double equal operator we compare them using only their values, meaning if a variable A contains some value and variable B contains some other value and we did `A == B` what will happen is that JavaScript will check their current values and return `true` if they are equal.

but what if we did something like this: `"1" == 1`, what would be the result of such expression? 

A normal person with some logical understanding would definitely guess that the output would be `false` because we are comparing a string to a number even if they have the same characters.

What will actually happen is that this output will be expressed as `true`. Why is that? When we use the double equal operator JavaScript will attempt to convert and compare operands of different types, meaning that they both would be converted to the same type and in case of comparing a  number to a string JavaScript will try and convert the string to a number type like this: `Number("1") == 1` which will output in that case `true`.

What if we have a case in which we actually want to compare the types of the variables we have and then compare their values without attempting any conversion? 
In that case, using the triple equal operators or the **Strict equality** would come in handy, what the strict equality operator simply does is checking if the operands are of the same type and then checks if they have the same value or not.

```js
let a = "1";
let b = 1;

console.log(a == b) // true;
console.log(a === b) // false;
```

We could simply imagine that JavaScript under the hood does something like this when using the strict equality:

```js
let a = "1";
let b = 1;

console.log(typeof a == typeof b && a == b)  // in case of doing a === b;
```

## What is `NaN` 

According to the MDN documentation `NaN` is:

> NaN is a property of the global object. In other words, it is a variable in global scope.

So basically `NaN` is simply a global object that describes what a not number is or whenever we have a variable that we are attempting to convert to a number and we fail it simply gives us `NaN` like this:

```js
let a = "hello world";
let convertedToNumber = Number(a);

console.log(convertedToNumber); // NaN;
```

## What is `typeof`

`typeof` is simply a JavaScript operator that returns a string that indicates the type of an operand.

There are basically 9 types in JavaScript:

- Undefined	"undefined"
- Null	"object" (see below)
- Boolean	"boolean"
- Number	"number"
- BigInt "bigint"
- String	"string"
- Symbol "symbol"
- Function object (implements [[Call]] in ECMA-262 terms)	"function"
- object	"object"

Whenever `typeof` is used one of these types would be the result, an example for that would be:

```js
typeof "" // string;
typeof 1 // number;
typeof function() {} // function;
typeof true // boolean;
```


## Why `NaN === NaN` returns `false`?

And finally, let us get into the core of this article, why when we explained how strict equality works and what is NaN does this expression provide us with a falsy value?

let us simplify the answer by looking into the strict equality comparison algorithm:

let us define the following two operands: x, and y. 

according to the JavaScript documentation ( This is a snippet from the docs ), the comparison algorithm works in the following matter:

The comparison x === y, where x and y are values, produces true or false. Such a comparison is performed as follows:

> If Type(x) is Number, then
> If x is NaN, return false.
> If y is NaN, return false.

This means that the algorithm first checks if one of the operands is `NaN` before even checking their types and if so it will return `false` anyways.

This may be a weird implementation of the comparison algorithm but there are some workarounds for this, we could use built-in functions like `Number.isNaN()` to check whether the giving parameter is a `NaN` or not instead of comparing it with `NaN` directly

```js
let invalidNumber = Number("asdasdasd"); // NaN;

let resultOfNormalComparison = invalidNumber === NaN; // false;
let resultOfBuiltInComparison = Number.isNaN(invalidNumber); // true;
```

**Edit**:
This part is being edited after recieving comments about why actually NaN is not equal to NaN from a mathematical prespective, I came accross this answer in stackoverflow and it helped me alot, would recommend it to anyone: [answer](https://stackoverflow.com/questions/1565164/what-is-the-rationale-for-all-comparisons-returning-false-for-ieee754-nan-values/1573715#1573715)

## Conclusion

You could somehow disagree on the implementation of the comparison algorithm but there are workarounds to check if a given variable or parameter is a `NaN` or not as shown above.

References:
- [Comparison algorithm](https://es5.github.io/#x11.9.6)
- [Typeof guide](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof)
- [NaN guide](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN)