## DEV Community

Amr Mohamed

Posted on • Updated on

# Why NaN === NaN returns false in JavaScript ?!

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

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

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

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

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

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

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

Alex Lohr

This explains what NaN is, but not the reason why Brendan Eich came up with it, which is: in algebraic functions, there may be undefined results, for example `Math.sqrt(-1)`. If one would be handling these results as undefined, they would be coerced to zero in further operations, which could lead to results that are mistaken for correct ones. Thus every mathematical operation with NaN yields NaN and comparisons always fail.

Jesse Phillips • Edited

It is because the floating point standard requires it en.m.wikipedia.org/wiki/IEEE_754

And as Alex Lohr points out this is very important in mathematics because

``````var a = 6 + 9;
var b = average() - 3;

if(a  < b)...
``````

If average() is NAN, `b` is NAN, the condition is false. Now that does not mean an else clause can assume `a >= b` because that is also false. But this ensures we don't try `average() == mean()` and go down a path where clearly we don't know.

Jakub T. Jankiewicz

Note that you didn't actually explained why NaN === NaN return false. You only explained that this is how it works. But the reason is because of IEEE 754 floating-point standard that specified how NaN should behave en.wikipedia.org/wiki/NaN

Amr Mohamed

Yep, I added a reference explaining it further more

Amr Mohamed

That is correct, thanks for the addition!