NaN, not a number, is a special ~~type~~ value used to denote an unrepresentable value. With JavaScript, `NaN`

can cause some confusion, starting from its `typeof`

and all to the way the comparison is handled.

Several operations can lead to `NaN`

as the result. Here are some examples (follow along on JSBin: jsbin.com/yulef):

Math.sqrt(-2) Math.log(-1) 0/0 parseFloat('foo') |

The first trap for many JavaScript beginners is usually the unexpected result of calling `typeof`

:

console.log(typeof NaN); // 'number' |

In a way, while NaN isn’t supposed to be a number, its type is number. Got it?

Stay calm, as this will continue to lead to many confusing paths. Let’s compare two NaNs:

var x = Math.sqrt(-2); var y = Math.log(-1); console.log(x == y); // false |

Maybe that’s because we’re supposed to use strict equal (===) operator instead? Apparently not.

var x = Math.sqrt(-2); var y = Math.log(-1); console.log(x === y); // false |

Arrgh! Could it be because they are NaNs from two different operations? What about…

var x = Math.sqrt(-2); var y = Math.sqrt(-2); console.log(x == y); // false |

Even crazier:

var x = Math.sqrt(-2); console.log(x == x); // false |

What about comparing two real NaNs?

console.log(NaN === NaN); // false |

Because there are many ways to represent a NaN, it makes sense that one NaN will not be equal to another NaN. Still, this is the reason why I sometimes tweet:

This is your annual reminder that NaN stands for "Not a NaN".

— Ariya Hidayat (@AriyaHidayat) October 23, 2013

To solve this, originally I intended to submit this proposal for ECMAScript 7:

But of course, solutions (and workarounds) already exist today.

Let’s get to know the global function isNaN:

console.log(isNaN(NaN)); // true |

Alas, `isNan()`

has its own well-known flaws:

console.log(isNaN('hello')); // true console.log(isNaN(['x'])); // true console.log(isNaN({})); // true |

This often leads to a number of different workarounds. One example is to exploit the non-reflective nature of NaN (see e.g. Kit Cambridge’s note):

var My = { isNaN: function (x) { return x !== x; } } |

Another example is to check for the value’s type first (to prevent coercion):

My.isNaN = function(x) { return typeof x === 'number' && isNaN(x); }; |

**Note**: The coercion that is being blocked here is related to `isNaN`

. As an exercise, compare the result of `isNaN(2)`

, `isNaN('2')`

and `isNaN('two')`

.

Fortunately, for the upcoming ECMAScript 6, there is `Number.isNaN()`

which provides a true `NaN`

detection (BTW, you can already use this function in the latest version of Chrome and Firefox). In the latest draft from April 2014 (Rev 24), this is specified in Section 20.1.2.4:

When the Number.isNaN is called with one argument number, the following steps are taken:

1. If Type(number) is not Number, return false.

2. If number is NaN, return true.

3. Otherwise, return false.

In other words, it returns `true`

only if the argument is *really* NaN:

console.log(Number.isNaN(NaN)); // true console.log(Number.isNaN(Math.sqrt(-2))); // true console.log(Number.isNaN('hello')); // false console.log(Number.isNaN(['x'])); // false console.log(Number.isNaN({})); // false |

Next time you need to deal with NaN, be extremely careful!