Confusion between isNaN and Number.isNaN in javascript
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.
Solution 1:
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
Solution 2:
-
isNaN
converts the argument to aNumber
and returns true if the resulting value isNaN
. -
Number.isNaN
does not convert the argument; it returns true when the argument is aNumber
and isNaN
.
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
Solution 3:
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.