57

I have a variable x and I want to test if x is set to NaN. How do I do that?

My first instinct is probably to, you know, test it, like this:

if (x === NaN) {  ...

Silly rabbit, no, that would be far too easy. NaN is like NULL in SQL, it is not equal to anything, even itself.

But look, there is a function called isNaN() -- maybe that will do it!

No, so far as I can tell, isNaN() is utterly worthless.

For example, isNaN([""]) properly returns false, but isNaN(["."]) returns true. You don't want do know how I learned about this flaw.

How do I do this?

Turns out, my question is a duplicate of this one, but the selected answer is wrong. The right answer has 20% as many upvotes.

wonea
  • 4,783
  • 17
  • 86
  • 139
Michael Lorton
  • 43,060
  • 26
  • 103
  • 144
  • "*You don't want do know how I learned about this flaw.*" - I wonder why you would call `isNaN` on an array? – Bergi May 19 '15 at 03:50
  • 1
    @Bergi -- I was writing a date-picker. I almost punched the screen when `["2015", "05", "05"]` was marked as NaN. – Michael Lorton May 19 '15 at 04:35
  • But why are you expecting an array to behave like a number at all? – Bergi May 19 '15 at 04:37
  • 1
    @Bergi -- I am not. Angular is giving me NaN to mean "the data isn't available yet", and the actual data (which in this case is an array) when it is. I need a way to know whether the data is there. – Michael Lorton May 19 '15 at 04:49
  • OK, then I'd rather use `Array.isArray` to detect the data, instead of detecting its absence. – Bergi May 19 '15 at 04:50
  • 1
    @Bergi -- if you look at [the original question](http://stackoverflow.com/questions/30313950/when-is-render-of-ngmodel-called-with-real-data), you can see the issue: Angular calls ngModel.$render with NaN if the data isn't ready and with the data if it is. The data is an array in one case, but there are lots of other cases. Of course, there is no reason that NaN itself couldn't be a legal value... – Michael Lorton May 19 '15 at 04:56
  • As regards the answer to [my question](http://stackoverflow.com/questions/2652319/how-do-you-check-that-a-number-is-nan-in-javascript?noredirect=1#comment59397346_2652319), I was asking how to check that a *number* is NaN, not how to check whether *any* value is NaN. So I guess this question actually *isn’t* answered by the answers to mine, and thus isn’t a duplicate. – Paul D. Waite Mar 08 '16 at 12:46

3 Answers3

73

Short Answer

For ECMAScript-5 Users:

#1
if(x !== x) {
    console.info('x is NaN.');
}
else {
    console.info('x is NOT a NaN.');
}

For people using ECMAScript-6:

#2
Number.isNaN(x);

And For consistency purpose across ECMAScript 5 & 6 both, you can also use this polyfill for Number.isNan

#3
//Polyfill from MDN
Number.isNaN = Number.isNaN || function(value) {
    return typeof value === "number" && isNaN(value);
}
// Or
Number.isNaN = Number.isNaN || function(value) {     
    return value !== value;
}

Note: I prefer to test using #1 which works same all places and does not have dependency on latest JS also. (It always gives me correct result. No surprises!)


Detailed Explanation:

Here is our awesome NaN

NaN == NaN; // false
NaN === NaN; // false

Please don't blame JavaScript for this, it is NaN which is supposed to behave this way in other languages also Which is fine as per rationale for all comparisons returning false NaN values

So comes isNaN as our savior, but wait it acts little differently in some scenarios like

isNaN(undefined); // true
isNaN({});        // true
isNaN("lorem ipsum"); // true

I had some strange faces by seeing the results above. And here comes reason from MDN

When the argument to the isNaN function is not of type Number, the value is first coerced to a Number. The resulting value is then tested to determine whether it is NaN.

So how should we test NaN for the non-numbers variables at all? I always go by the following

if(x !== x) {
    console.info('Is a NaN');
}
else {
    console.info('Not a NaN');
}

ECMAScript-6/JavaScript-2015 Updates

Do we have anything in ECMAScript-6 for the same. Yup we do...

Number.isNaN(x); // true

The ES6 implementation will also be helpful for the above cases like

Number.isNaN(undefined); // false
Number.isNaN({}); // false    
Number.isNaN("lorem ipsum"); // false

whereas ECMAScript-5 global function isNaN outputs in true for the above cases, which sometimes may not align with our expectation.

Community
  • 1
  • 1
dopeddude
  • 4,943
  • 3
  • 33
  • 41
  • 2
    like `isNaN( "" ) = false` and `isNaN( {} ) = true` while `Number.isNaN( "" ) = false` and `Number.isNaN( {} ) = false` – loretoparisi Nov 07 '16 at 17:16
  • Polyfill could also be as simple as `Number['isNaN'] || (Number.isNaN = function(a) { return a !== a });` Basically the same, minus a handful or so of chars and with the variable set moved to the other side of the operator. – SpYk3HH Jan 24 '17 at 21:48
  • Read more about isNaN() here: https://www.w3schools.com/jsref/jsref_isnan.asp – Srijan Chaudhary Jan 14 '20 at 04:11
27

The question has the answer if you read closely enough. That is the way I found it: I was typing out the question and... bingo.

You remember when I wrote "NaN is like NULL in SQL, it is not equal to anything, even itself"? So far as I know, NaN is the only value in Javascript with this property. Therefore you can write:

var reallyIsNaN = function(x) {
   return x !== x;
};
Michael Lorton
  • 43,060
  • 26
  • 103
  • 144
  • After reading [MDN docs for Number.NaN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN), it suggests to also check if `typeof x === "number"`. `isNaN` is different in that it coerces the value to a number before comparing (`+[] == 0`, wat?) – thgaskell May 19 '15 at 00:15
  • @thgaskell When you say +[] == 0 what happens is that javascript tries to convert the first value of the array to integer. Try to call array[0] un an empty array and it will return undefined. This conversion is not equal that of parseInt and undefined will be converted to 0, try +[1] and + ['1223fsds']. Finally 0 == 0. That's why you get that result. – devconcept May 19 '15 at 01:36
  • @thgaskell Yes I saw the video. It was hilarious. Check this post http://stackoverflow.com/questions/30325896/why-using-the-unary-operator-on-an-array-gives-inconsistent-results-in-javascr/30326359 – devconcept May 19 '15 at 13:38
  • 1
    @thgaskell - wat is not [wat](https://www.youtube.com/watch?v=ynENRrsjqqI). – Michael Lorton Jan 06 '17 at 19:10
  • Please keep calm and remember that Java, C#, Python, Scala, C++ (under clang, g++ and msvc) all have the same NaN behaviour as JavaScript. In all of those languages `0/0` is NaN and in all of them NaN is not equal to itself. It is simply [what the standard requires](https://en.wikipedia.org/wiki/IEEE_754) – Benjamin Gruenbaum Aug 26 '18 at 14:19
  • @BenjaminGruenbaum — Standards are not moral imperatives. The usual arguments for adhering to the standards are (1) they represent Best Practices in the considered opinion of a group of experts and (2) they are what the user is likely to expect. Neither of those obtain in this case. – Michael Lorton Aug 26 '18 at 18:58
  • Perhaps, but this is more of a CPU architecture problem than a JavaScript one - JavaScript is simply doing what every other language in the world is doing in this case. – Benjamin Gruenbaum Aug 26 '18 at 19:02
  • What if x is "2"? This would fail. Because `x="2"; x !==x; // is false` – SamuraiJack Aug 06 '19 at 18:32
0

It looks like an overkill but how about trying this?:

if (Number(dataInput) !== Number(dataInput))
{
    ...
}
Lee Taylor
  • 7,761
  • 16
  • 33
  • 49
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Ethan Jun 10 '22 at 01:13