# The Curious Case of JavaScript NaN

# The Curious Case of JavaScript NaN

Join the DZone community and get the full member experience.

Join For FreeMicroservices. Streaming data. Event Sourcing and CQRS. Concurrency, routing, self-healing, persistence, clustering...learn how Akka enables Java developers to do all this out of the box! Brought to you in partnership with Lightbend.

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!

Microservices. Streaming data. Event Sourcing and CQRS. Concurrency, routing, self-healing, persistence, clustering...learn how Akka enables Java developers to do all this out of the box! Brought to you in partnership with Lightbend.

Published at DZone with permission of Ariya Hidayat , DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

## {{ parent.title || parent.header.title}}

## {{ parent.tldr }}

## {{ parent.linkDescription }}

{{ parent.urlSource.name }}