88

I have a confusion in how NaN works. I have executed isNaN(undefined) it returned true . But if I will use Number.isNaN(undefined) it is returning false. So which one i should use. Also why there is so discrepancy in the result.

Salman A
  • 262,204
  • 82
  • 430
  • 521
Pranjal Diwedi
  • 1,012
  • 1
  • 7
  • 8
  • 8
    **Answer:** `Due to both equality operators, == and ===, evaluating to false when checking if NaN is NaN, the function Number.isNaN() has become necessary. In comparison to the global isNaN() function, Number.isNaN() doesn't suffer the problem of forcefully converting the parameter to a number. This means it is now safe to pass values that would normally convert to NaN, but aren't actually the same value as NaN. This also means that only values of the type number, that are also NaN, return true.` – Tushar Oct 16 '15 at 07:28
  • didn't know about this. Most of the time I use isNaN() – Rudra Oct 16 '15 at 07:35
  • Maybe use [Number.isFinite](https://mdn.io/Number/isFinite)? – Elias Zamaria Apr 02 '21 at 22:05
  • Does this answer your question? [Is Number.IsNaN() more broken than isNaN()](https://stackoverflow.com/questions/25176459/is-number-isnan-more-broken-than-isnan) – Boghyon Hoffmann Jul 13 '21 at 15:07

6 Answers6

99

To quote from a ponyfoo article on numbers in ES6:

Number.isNaN is almost identical to ES5 global isNaN method. Number.isNaN returns whether the provided value equals NaN. This is a very different question from “is this not a number?”.

So isNaN just checks whether the passed value is not a number or cannot be converted into a Number. Number.isNaN on the other hand only checks if the value is equal to NaN (it uses a different algorithm than === though).

The String 'ponyfoo' for example is not a number and cannot be converted into a number, but it is not NaN.

Example:

Number.isNaN({});
// <- false, {} is not NaN
Number.isNaN('ponyfoo')
// <- false, 'ponyfoo' is not NaN
Number.isNaN(NaN)
// <- true, NaN is NaN
Number.isNaN('pony'/'foo')
// <- true, 'pony'/'foo' is NaN, NaN is NaN

isNaN({});
// <- true, {} is not a number
isNaN('ponyfoo')
// <- true, 'ponyfoo' is not a number
isNaN(NaN)
// <- true, NaN is not a number
isNaN('pony'/'foo')
// <- true, 'pony'/'foo' is NaN, NaN is not a number
nils
  • 25,734
  • 5
  • 70
  • 79
  • 2
    In other words, it's not "almost identical" :) – Nahn Feb 07 '23 at 17:07
  • @Nahn . . . Correct. The quote even seems to contain a contradiction: "almost identical" vs. "very different question". IMHO, nils' answer is quite enlightening and doesn't need that confusing quote. – Bart Hofland Feb 21 '23 at 10:41
35
  • isNaN converts the argument to a Number and returns true if the resulting value is NaN.
  • Number.isNaN does not convert the argument; it returns true when the argument is a Number and is NaN.

So which one i should use.

I am guessing you are trying to check if the value is something that looks like a number. In which case the answer is neither. These functions check if the value is an IEEE-754 Not A Number. Period. For example this is clearly wrong:

var your_age = "";
// user forgot to put in their age
if (isNaN(your_age)) {
  alert("Age is invalid. Please enter a valid number.");
} else {
  alert("Your age is " + your_age + ".");
}
// alerts "Your age is ."
// same result when you use Number.isNaN above

Also why there is so discrepancy in the result.

As explained above Number.isNaN will return false immediately if the argument is not a Number while isNaN first converts the value to a Number. This changes the result. Some examples:

                |       Number.isNaN()       |        isNaN()
----------------+----------------------------+-----------------------
value           | value is a Number | result | Number(value) | result
----------------+-------------------+--------+---------------+-------
undefined       | false             | false  | NaN           | true
{}              | false             | false  | NaN           | true
"blabla"        | false             | false  | NaN           | true
new Date("!")   | false             | false  | NaN           | true
new Number(0/0) | false             | false  | NaN           | true
Salman A
  • 262,204
  • 82
  • 430
  • 521
20

I found that if you want to check if something is numbery (or not), then a combination of Number.isNaN() with either Number.parseInt() or Number.parseFloat() (depending on what you expect) to cover most use cases:

consider: test a bunch of different input vars against several is number tests:

r = [NaN, undefined, null, false, true, {}, [], '', ' ', 0, 1, '0', '1']
.map(function(v){return [
    v, 
    isNaN(v), 
    Number.isNaN(v), 
    Number.isInteger(v),
    Number.parseInt(v, 10), 
    Number.isNaN( Number.parseInt(v, 10)) 
];});
console.table(r);
// or if console.table() not available:
r.join('\n', function(v){v.join(',')} );

result:

NaN      , true , true , false, NaN, true 
undefined, true , false, false, NaN, true 
null     , false, false, false, NaN, true 
false    , false, false, false, NaN, true 
true     , false, false, false, NaN, true 
Object   , true , false, false, NaN, true 
Array(0) , false, false, false, NaN, true 
''       , false, false, false, NaN, true 
' '      , false, false, false, NaN, true 
0        , false, false, true , 0  , false
1        , false, false, true , 1  , false
'0'      , false, false, false, 0  , false
'1'      , false, false, false, 1  , false

Note the last column, which is usually what I want in my experience.

MoonLite
  • 4,981
  • 2
  • 21
  • 13
6

In shortly,

isNaN()

will check if the convert of value to Number (type) are failed

For example'abc'


Number.isNaN()

will check if the given value type is Number but not valid number

For example: 'bb'/33

ofir_aghai
  • 3,017
  • 1
  • 37
  • 43
3

First, forget about the useless meaning of the value NaN, just treat it as bad number. As soon as you saw NaN, read it as 'bad number'.

Number.isNaN is a more safe and robust version of isNaN, isNaN has a bug,

isNaN(NaN) // true, this is the supposed result, the argument is NaN
isNaN('hello') // true, but this is misleading, cuz `hello` is not NaN

isNaN can't distinguish NaN with other not-number values, such as characters.

So a new method comes into play.

Number.isNaN checks if the value is number firstly, if it is not a number, it returns false immediately.

Number.isNaN('hello') // false, 'hello' is not NaN, this is the supposed result

sfy
  • 2,810
  • 1
  • 20
  • 22
2

Number.isNaN()

This method returns true if the value is of the type Number, and equates to NaN. Otherwise it returns false. e.g.

Number.isNaN(123) //false

Type of 123 is number but 123 is not equal to NaN, therefore it returns false.


Number.isNaN('123') //false
    
Type of 123 is string & '123' is not equal to NaN, therefore it returns false.


Number.isNaN(NaN) //true

Type of NaN is number & NaN is equal to NaN, therefore it returns true.


Number.isNaN('NaN') //false

Type of 'NaN' is string & 'NaN' is not equal to NaN, therefore it returns false.

global isNaN() function

The global isNaN() function converts the tested value to a Number, then tests it.

isNaN(123) //false
isNaN('123') //false
isNaN(NaN) //true
isNaN('NaN') //true
Vikram Sapate
  • 1,087
  • 1
  • 11
  • 16