typeof(Infinity) returns Number in Javascript.
But why doesn't x.isNaN, where x = 1/0, return Number ?
Sample code:
var x = 1/0;
document.write(typeof(x)); //returns Number
document.write(x.isNaN); //return undefined
P.S: I am new to Javascript and learning it from W3Schools. I would be glad if you can direct me to any other reliable resources.
isNan is not a property of any number. isNaN, however, is both a function on the global scope, and on the Number object. (With the latter one being newer / more robust version)
Since isNaN is a function, you'll have to pass the variable you'd like to check as an argument:
isNaN(x) or Number.isNaN(x) will return true, as you expected.
The reason document.write(x.isNaN); returns undefined, is because x (a Number) doesn't have the property isNan.
Numbers (including NaN) don't have an isNaN method. It's global. What you want is actually isNaN(x). (Note the capital N.)
isNaN is not a property, it is a global function or a Number static method (won't work on instantiated variables).
you'll have to use either:
isNaN(x);
Number.isNaN(x);
Preferencially, Number.isNaN, although it isn't supported in IE, Opera or Safari yet.
what is NaN, Object or primitive?
NaN - Not a Number
It's a primitive. You can check in a number of ways:
typeof NaN gives "number," not "object."
Add a property, it disappears. NaN.foo = "hi"; console.log(NaN.foo) // undefined
NaN instanceof Number gives false (but we know it's a number, so it must be a primitive).
It wouldn't really make sense for NaN to be an object, because expressions like 0 / 0 need to result in NaN, and math operations always result in primitives. Having NaN as an object would also mean it could not act as a falsey value, which it does in some cases.
NaN is a primitive Number value. Just like 1, 2, etc.
NaN is a property of the global object.
The initial value of NaN is Not-A-Number — the same as the value of
Number.NaN. In modern browsers, NaN is a non-configurable,
non-writable property. Even when this is not the case, avoid
overriding it.
It is rather rare to use NaN in a program. It is the returned value
when Math functions fail (Math.sqrt(-1)) or when a function trying to
parse a number fails (parseInt("blabla")).
Reference
We can do:
NaN = 'foo'
as well as
undefined = 'foo'
Why are they not reserved keywords?
I think it should be implemented in order to be sure that when we are looking for a number, it is a number :)
If we should use IsNaN() or typeof, why are NaN or undefined needed?
I cannot tell you why, but undefined and NaN are actually properties of the global object:
15.1.1 Value Properties of the Global Object
15.1.1.1 NaN
The value of NaN is NaN (see 8.5). This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.
(...)
15.1.1.3 undefined
The value of undefined is undefined (see 8.1). This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.
There is a difference between the value undefined (NaN) and the corresponding property.
You might notice the [[Writable]]: false. I'm not sure whether this new in ES5 (and might not be adapted by all browsers), but in newer browsers (tested in Firefox 6), assigning a new value to undefined has no effect:
[12:28:15.090] < undefined = "foo"
[12:28:15.093] > "foo"
[12:28:19.882] < undefined
[12:28:19.883] > undefined
So although it seems you can assign a new value, you actually cannot.
Why they are not reserved keywords?
Not sure if there was a specific reason to not make them reserved keywords, but it was decided against it. The language still works. You cannot override these values, so it's fine.
The only way to test whether a number is NaN, is to use isNaN() anyway.
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/NaN
NaN is a property of the global object.
The initial value of NaN is Not-A-Number — the same as the value of
Number.NaN. In modern browsers, NaN is a non-configurable,
non-writable property. Even when this is not the case, avoid
overriding it.
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/undefined
undefined is a property of the global object, i.e. it is a variable in global scope.
The initial value of undefined is the primitive value undefined.
I'm speculating now, but the reason why I think NaN and undefined are not keywords is because you generally don't assign these values to variables.
var x = undefined; // doesn't make sense, use null!
var y = NaN; // You can't do much with this variable!
undefined basically means uninitialized, and if you want to make it clear that the value is unknown you use null. So undefined usually means not-initialized or the result of JavaScript code gone wrong.
NaN Is rarely assigned manually, simply because you can't do much with this value. It is usually the result of a calculation gone wrong. The makers of JavaScript probably didn't want to give this value the visibility of primitive values.
Also, NaN is also present in other languages and it isn't used as a keyword there either. For example: In C# NaN is represented by Double.NaN, since you don't make a distinction between floating point and integer values in JavaScript, I'm guessing that's why they put NaN with the Global Identifiers!
I hope this clears things up!
Both NaN and undefined are values in JavaScript.
NaN is of number type. (it denotes "not a valid number").
undefined is of undefined type. (when there is nothing assigned to a variable, JavaScript assigned undefined particular in var declaration).
And also both are read-only values(property) of global window object.
So that's why JavaScript cannot make values as a reserved word.
NaN is not a keyword, but it is rather a built-in property of the global object, and as such may be replaced (like undefined, but unlike the keyword this or the literals true, false, and null).
You can test if a value is NaN with the isNaN() function. Moreover NaN is defined to be unequal to everything, including itself.
Or in a nutshell you can say that:
NaN is the value returned when you try to treat something that is not a number as a number. For instance, the results of 7 times "abc" is not a number. The old form of it is Number.NaN. You can test for not-a-number values with the isNaN() function.
One reason is that it is possible to use those words as object keys:
messages = {
NaN: 'that was not a number',
undefined: 'that was not initialized',
default: 'that was something' // not in the original question but is valid syntax
};
console.log (messages.NaN);
While it would be possible to use { 'NaN': 'that was not a number' } and console.log(messages['NaN']), leaving as many words as possible unreserved could make your code easier to read.
This code in JS gives me a popup saying "i think null is a number", which I find slightly disturbing. What am I missing?
if (isNaN(null)) {
alert("null is not a number");
} else {
alert("i think null is a number");
}
I'm using Firefox 3. Is that a browser bug?
Other tests:
console.log(null == NaN); // false
console.log(isNaN("text")); // true
console.log(NaN == "text"); // false
So, the problem seems not to be an exact comparison with NaN?
Edit: Now the question has been answered, I have cleaned up my post to have a better version for the archive. However, this renders some comments and even some answers a little incomprehensible. Don't blame their authors. Among the things I changed was:
Removed a note saying that I had screwed up the headline in the first place by reverting its meaning
Earlier answers showed that I didn't state clearly enough why I thought the behaviour was weird, so I added the examples that check a string and do a manual comparison.
I believe the code is trying to ask, "is x numeric?" with the specific case here of x = null. The function isNaN() can be used to answer this question, but semantically it's referring specifically to the value NaN. From Wikipedia for NaN:
NaN (Not a Number) is a value of the numeric data type representing an undefined or unrepresentable value, especially in floating-point calculations.
In most cases we think the answer to "is null numeric?" should be no. However, isNaN(null) == false is semantically correct, because null is not NaN.
Here's the algorithmic explanation:
The function isNaN(x) attempts to convert the passed parameter to a number1 (equivalent to Number(x)) and then tests if the value is NaN. If the parameter can't be converted to a number, Number(x) will return NaN2. Therefore, if the conversion of parameter x to a number results in NaN, it returns true; otherwise, it returns false.
So in the specific case x = null, null is converted to the number 0, (try evaluating Number(null) and see that it returns 0,) and isNaN(0) returns false. A string that is only digits can be converted to a number and isNaN also returns false. A string (e.g. 'abcd') that cannot be converted to a number will cause isNaN('abcd') to return true, specifically because Number('abcd') returns NaN.
In addition to these apparent edge cases are the standard numerical reasons for returning NaN like 0/0.
As for the seemingly inconsistent tests for equality shown in the question, the behavior of NaN is specified such that any comparison x == NaN is false, regardless of the other operand, including NaN itself1.
I just ran into this issue myself.
For me, the best way to use isNaN is like so
isNaN(parseInt(myInt))
taking phyzome's example from above,
var x = [undefined, NaN, 'blah', 0/0, null, 0, '0', 1, 1/0, -1/0, Number(5)]
x.map( function(n){ return isNaN(parseInt(n))})
[true, true, true, true, true, false, false, false, true, true, false]
( I aligned the result according to the input, hope it makes it easier to read. )
This seems better to me.
(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.
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! (Edit: Except it turns out isNaN is only defined over Number, in which case it works just fine -- just with a misleading name.)
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
Null is not NaN, as well as a string is not NaN. isNaN() just test if you really have the NaN object.
In ES5, it defined as isNaN (number) returns true if the argument coerces to NaN, and otherwise returns false.
If ToNumber(number) is NaN, return true.
Otherwise, return false.
And see the The abstract operation ToNumber convertion table. So it internally js engine evaluate ToNumber(Null) is +0, then eventually isNaN(null) is false
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'.
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.
(NaN == null) // false
(NaN != null) // true
Funny though:
(NaN == true) // false
(NaN == false) // false
(NaN) // false
(!NaN) // true
Aren't (NaN == false) and (!NaN) identical?