Why NaN !== NaN

Nick Gard
3 min readMay 14, 2019
Photo by Jeremy Thomas on Unsplash

Among the many seeming oddities of JavaScript is the fact that NaN (Not-a-Number) is not equal to itself. Countless beginners have written conditionals checking if n === NaN, only to find that this is never true. The solution, of course, is to use the built-in checker, Number.isNaN(). Confusion over this inequality often boils over to agitation and unfair condescension at the JavaScript language.

I’m here to tell you that NaN !== NaN is a feature of JavaScript and not a bug.

Why shouldn’t NaN be equal to itself? Because that would lead to bad comparisons. NaN is coalescing, meaning that any mathematical operation done with NaN results in NaN. If two complex calculations were done and then their results compared, you would expect them to be equal if and only if they yielded the same number. Suppose there was an error in the calculations or in the input value and they each resulted in NaN. They should not be considered equal here because not all failures are equal.

function avg(num1, num2) {
return (num1 + num2) / 2;
}
// both are NaN and SHOULD NOT be equal
avg('1.2', '2.2') === avg('1.3', '2.3')

If bad calculations returned null or undefined instead of NaN, then false equivalences would abound.

Why is NaN a Number type? You might expect something called Not-a-Number to not be a number, but typeof NaN === "number". This is needed in order for NaN to work the way it does. It has to inherit from the Number prototype so that any mathematical operations performed with it do not throw errors.

A variable holding a number or possibly a NaN can still have toPrecision() called on it. If NaN weren’t a Number type, you would have to check for it before doing any and every mathematical operation. That would get tedious! Yet another reason that bad calculations in JavaScript return NaN instead of null or undefined.

Keep these reasons in mind the next time you write a function that returns a number. You may wish to return NaN for the “bad paths” of the function, rather than something else.

Note that there are two isNaN() methods in JavaScript: the global one and the one in the Number object. There’s a subtle but significant difference in them. The global isNaN() method coerces its argument into a number first, meaning that undefined, {}, 'NaN', and many other inputs return true. (This means isNaN(undefined) === true, even though undefined is clearly not NaN.)

Number.isNaN(), however, does not coerce its argument. It will return true if and only if its argument is actually NaN. This is probably the method you want to use. It is a newer addition to ECMAScript (the JavaScript specification) and it is supported in every browser except Internet Explorer. Fortunately, writing your own polyfill is easy since NaN is the only value not equal to itself:

function isNaN(n) {
return n !== n;
}

--

--