.

Tags:

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:

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

nan

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!

  • Kirill Dmitrenko

    > console.log(isNaN(‘hello’)); // true

    Why is this a flaw? I think, it’s only logical: VM will try to cast ‘hello’ string to a number, and this operation will give us NaN. And isNaN(NaN) is obviously true. The same situation with array and object.

    • Rich Waters

      The idea is to be able to differentiate the actual NaN value from other values that are also not a number. Obviously String/Object/Array are not Numbers, and have reasonable responses to typeof making them straight-forward to detect. The work-around functions are usable at the moment, but it still seems like a function called isNaN should really be providing us with the mechanism to detect an actual NaN value.

    • Ai_boy

      Then why isNaN(‘1′) == false? String ‘1’ is not a number! ( I know why but this is still unlogical )

    • student

      i think in function isNaN(number) ,when Type(number) is not Number,then call function parseInt

  • Frerich Raabe

    If you assert that `==` is transitive, then there’s another case of a value not being equal to itself:

    > ‘0’ == ” && ” == 0 && 0 == ‘0’

    false

    Oddly enough, the first comparison is false whereas the other two are true and hence ‘0’ does not equal ‘0’ if you assume that ‘==’ is transitive.

  • http://webplatformdaily.org Šime Vidas

    Oh cool. They only needed 2 tries to get isNaN() right :-P

    • http://ariya.ofilabs.com/ Ariya Hidayat

      Better late than never :-)

  • Alejandro Gomez

    this is so embarrassing for javascript :P

    • http://ariya.ofilabs.com/ Ariya Hidayat

      Before saying that, check isnan behavior in your favorite language/programming environment. Be ready for a surprise!

      • Alejandro Gomez

        take my comment not as an offense, but as a joke.

        Javascript is a curious/weird language (I develop in node.js btw)

        Still that weirdness has advantages, and it is good (and I thank you) that people like you help us to note this behaviors.

        I leave you with this funny video about other weird behaviors https://www.destroyallsoftware.com/talks/wat

        kudos !

  • Mohammad Khan

    Nice explanation, love the GarlicNaN() != NaN reference!

  • http://www.poetro.hu/ Poetro

    This is the definition of NaN by IEEE 754, and nothing JavaScript related.

    “In computing, NaN, standing for not a number, is a numeric data type value representing an undefined or unrepresentable value, especially in floating-point calculations.”
    “A comparison with a NaN always returns an unordered result even when comparing with itself.”

    • http://ariya.ofilabs.com/ Ariya Hidayat

      True, but the main discussion points here are JavaScript typeof of NaN, isNaN, and Number.isNaN.

  • WebReflection

    I think there was no need to talk about coercion after Kit’s example since `===` or `!==` does not suffer coercion at all. I understand coercion in this case is related to the fact that `isNaN(“string”)` coerce somehow string to “Not A Number” but having Kit’s example in the middle confused me, thinking that extra example was related to the previous `===`. In few words I’d rather put Kit’s solution after the `typeof` one, or drop the latter completely since `NaN` is indeed the only value that does not `===` itself.

    • http://ariya.ofilabs.com/ Ariya Hidayat

      Thanks for the feedback! I mentioned coercion there so that any brave readers can explore the implication of isNaN() in depth, should they want to.

      I think it is fair to mention both the self-comparison and typeof solutions. After all, this post is intended to be informational and not opinionated. Also, the typeof trick faithfully follows what ES 6 standardizes on Number.isNaN.

      • WebReflection

        so, the short version of the feedback: I think it’s misleading in that order. if you want keep both cases, I’d put the “avoid coercion like this” before the “or use unique non reflective nature like Kit’s code” and nobody could possibly think that coercion is about the `===` (as I did, had to read three times to realize that coercion was about the snippet above the previous snippet) – or leave it as it is but then don’t ask me to write feedbacks here :P

        • http://ariya.ofilabs.com/ Ariya Hidayat

          I appreciate the feedback.

  • fengchang

    GarlicNaN? Sounds like a joke, is there any story in it?

    • reivax

      Try an idian restaurant.