Null is not NaN, as well as a string is not NaN. isNaN() just test if you really have the NaN object.
isNaN looks for numeric values that are not numbers - things like infinity, undeflow etc.; you could think of them as error codes for calculations. null is not one of these.
More information here.
I'm not exactly sure when it comes to JS but I've seen similar things in other languages and it's usually because the function is only checking whether null is exactly equal to NaN (i.e. null === NaN would be false). In other words it's not that it thinks that null is in fact a number, but it's rather that null is not NaN. This is probably because both are represented differently in JS so that they won't be exactly equal, in the same way that 9 !== '9'.
Here's the definitive answer:
The function isNaN attempts to convert the passed parameter to a number. If the parameter can't be converted, it returns true; otherwise, it returns false.
So in your case, null is converted to the number 0. (Try evaluating 'Number(null)' and see that it returns 0.) Then 0 is evaluated as being a number and isNaN returns false. A string that is only digits can be converted to a number and isNaN also returns false. A string that cannot be converted to a number will cause isNaN to return true.
In addition to these apparent edge cases are the standard numerical reasons for returning NaN like 0/0.
This is indeed disturbing. Here is an array of values that I tested:
var x = [undefined, NaN, 'blah', 0/0, null, 0, '0', 1, 1/0, -1/0, Number(5)]
It evaluates (in the Firebug console) to:
,NaN,blah,NaN,,0,0,1,Infinity,-Infinity,5
When I call x.map(isNaN)
(to call isNaN on each value), I get:
true,true,true,true,false,false,false,false,false,false,false
In conclusion, isNaN
looks pretty useless!
Incidentally, here are the types of those values:
x.map(function(n){return typeof n})
-> undefined,number,string,number,object,number,string,number,number,number,number
(My other comment takes a practical approach. Here's the theoretical side.)
I looked up the ECMA 262 standard, which is what Javascript implements. Their specification for isNan:
Applies ToNumber to its argument, then returns true if the result is NaN, and otherwise returns false.
Section 9.3 specifies the behavior of ToNumber
(which is not a callable function, but rather a component of the type conversion system). To summarize the table, certain input types can produce a NaN. These are type undefined
, type number
(but only the value NaN
), any object whose primitive representation is NaN
, and any string
that cannot be parsed. This leaves undefined
, NaN
, new Number(NaN)
, and most strings.
Any such input that produces NaN
as an output when passed to ToNumber
will produce a true
when fed to isNaN
. Since null
can successfully be converted to a number, it does not produce true
.
And that is why.
Note:
"1" == 1 // true
"1" === 1 // false
The == operator does type-conversion, while === does not.
Douglas Crockford's website, a Yahoo! JavaScript evangelist, is a great resource for stuff like this.
If isNaN(null) == false, then why does
testValue = null;
intValue = ((isNaN(testValue))? 0 : testValue);
alert(intValue);
tell me that 'intValue' is NaN? It seems inconsistent that null is treated like 0 by the isNaN function but not in normal arithmetic.