JavaScript: what is NaN, Object or primitive? - javascript

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

Related

If I have something that evaluates to NaN why doesn't it show equality to NaN

In the following code:
var notNum = 'dfsd'
Number(notNum) === NaN
The last expression evaluates to false. Do you know why? Is there no way to use NaN in a comparison?
typeof(Number(notNum)) === 'number'
This somehow evaluates to true. I really don't understand how NaN works..
NaN (Not-a-Number) is a global object in JS returned when some mathematical operation gets failed.
You can't compare an object with another object directly.
Either you have to use typeof which you are using or you can use Object.is()
Object.is(Number(notNum), NaN) // true

Why is "" == [null] true in JavaScript?

I know JavaScript has lots of insane results with comparisons between types, though I don't fully understand why. Came across this one today.
Why does
"" == [null]
evaluate to true in JavaScript?
Some more Javascript equality amusement, thanks to #Qantas:
Why does 2 == [2] in JavaScript?
Why is 0 == "" true in JavaScript
Why if([]) is validated while [] == false in javascript?
Why does !{}[true] evaluate to true in JavaScript?
The "Abstract Equality Comparison Algorithm" has many parts, but the important one here is this:
If Type(x) is either String or Number and Type(y) is Object,
return the result of the comparison x == ToPrimitive(y).
(There's a mirror-image of that too.) So, because "" is a string and [null] is an object, we've got to first convert [null] to a string by calling ToPrimitive([null]). That's an internal operation described as follows, when it's asked to convert an Object instance to a primitive value:
Return a default value for the Object. The default value of an object is retrieved by calling the [[DefaultValue]] internal method of the object, passing the optional hint PreferredType. The behaviour of the [[DefaultValue]] internal method is defined by this specification for all native ECMAScript objects in 8.12.8.
Now, the [[DefaultValue]] internal operation will call .toString() on the object and return that value. Try [null].toString() in your browser console:
> [null].toString()
""
And there you have it.
Edit: And why is [null].toString() an empty string? Because the .toString() operation on Array instances always just calls .join(), and that always yields an empty string for null and undefined values. Thus an array of one null ends up as just a single empty string.
It's according to the arcane type-conversion rules of Javascript. Rule #8:
If Type(x) is either String or Number and Type(y) is Object, return the result of the comparison x == ToPrimitive(y).
So the comparison is between x = "" and y = [null] converted to a string using ToPrimitive. Converting an array with one null element results in an empty string (because Array.toString() returns a comma-separated list of values), hence they evaluate to equal.
Why does "" == [null] evaluate to true?
Because you're comparing an array with a string, using the non-strict equality operator == - so it will try to cast values to the same type before comparing them.
What happens in detail is:
you compare a string to an object, so the object is cast to a string:
When an array is cast to a primitive value, it's .toString() method is invoked (as explained in detail by the other answers), which is equivalent to calling .join():
which in case of a one-element array that only contains an undefined or null value returns the empty string
which finally is equivalent to the empty string
This third step is the unexpected one ([null]+"" != null+""), if it actually did cast that to a string the result would have been "null" and your equality be false.
Let's look at the spec and follow through each step
Going via the Abstract Equality Comparison Algorithm (§11.9.3):
typeof ""; // string and typeof [null]; // object so not applicable
neither is null or undefined so not applicable
same as 2
neither is a number, not applicable
same as 4
neither is a bool, not applicable
again not applicable
finally, something applicable, now we need to know ToPrimitive([null])
§9.1 ToPrimitive for Objects says we need to work out [[DefaultValue]] (§8.12.8), points 1 and 2 of which say if you can do .toString and it gives a string, return that, so
[null].toString(); // ""
So we are now performing the comparison "" == "" which is true by the Abstract Equality Comparison Algorithm's point 1. d.
If Type(x) is String, then return true if x and y are exactly the same sequence of characters (same length and same characters in corresponding positions). Otherwise, return false.
JavaScript is weakly typed; you can use the following to get a false result:
"" === [null]
The value null is a JavaScript literal representing null or an "empty" value, i.e. no object value is present. It is one of JavaScript's primitive values.
The value null is a literal (not a property of the global object like undefined can be). In APIs, null is often retrieved in place where an object can be expected but no object is relevant. When checking for null or undefined beware of the differences between equality (==) and identity (===) operators (type-conversion is performed with the former).
typeof null // object (bug in ECMAScript, should be null)
typeof undefined // undefined
null === undefined // false
null == undefined // true

Why 'NaN' and 'Undefined' are not reserved keywords in JavaScript?

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.

what is the reserved keyword for NaN in javascript?

if i want to test the result of an expression and the function would return NaN
how would i check that?
examples: $('amount').value.toInt()!='NaN' ^ does not work and i assume that the returned value is not a string,
$('amount').value.toInt()!=NaN^ doesnt seem to work either and this one seems obvious
so how do i check wether the returned value is not a number?
The NaN value is defined to be unequal to everything, including itself. Test if a value is NaN with the isNaN() function, appropriately enough. (ECMAScript 6 adds a Number.isNan() function with different semantics for non-number arguments, but it's not supported in all browsers yet as of 2015).
There are two built-in properties available with a NaN value: the global NaN property (i.e. window.NaN in browsers), and Number.NaN. It is not a language keyword. In older browsers, the NaN property could be overwritten, with potentially confusing results, but with the ECMAScript 5 standard it was made non-writable.
As #some pointed out in the comments, there is also the global function isFinite() which may be useful.
the best way to check the result of numeric operation against NaN is to aproach this way ,
example:
var x = 0;
var y = 0;
var result = x/y; // we know that result will be NaN value
// to test if result holds a NaN value we should use the following code :
if(result !=result){
console.log('this is an NaN value');
}
and it's done.
the trick is that NaN can't be compared to any other value even with it self(NaN !=NaN is always true so we can take advantage of this and compare result against itself)
this is JavaScript(a good and bizarre language)
Equality operator (== and ===) cannot be used to test a value against NaN. Use Number.isNaN() or isNaN() instead.
NaN === NaN; // false
Number.NaN === NaN; // false
isNaN(NaN); // true
isNaN(Number.NaN); // true

Why is isNaN(null) == false in JS?

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?

Categories

Resources