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;
}