NaN and typeof
After writing the previous post in which I attempted to explain typeof null, a few people had questioned NaN’s behavior with the same operator (i.e., typeof NaN). Therefore, I’ve decided to write a similar post about this familiar, but often misunderstood, property.
First, NaN is not a keyword (unlike true, false, null, etc..), it is a property of the global object. The value of NaN is the same as the value of Number.NaN:
NaN; // NaN
Number.NaN; // NaN
There are several ways in which NaN can happen:
- Division of zero by zero
- Dividing an infinity by an infinity
- Multiplication of an infinity by a zero
- Any operation in which
NaNis an operand - Converting a non-numeric string or
undefinedinto a number
Why does typeof NaN return "number"?
typeof NaN; // "number"
The ECMAScript standard states that Numbers should be IEEE-754 floating point data. This includes Infinity, -Infinity, and also NaN.
By definition, NaN is the return value from operations which have an undefined numerical result. Hence why, in JavaScript, aside from being part of the global object, it is also part of the Number object: Number.NaN. It is still a numeric data type, but it is undefined as a real number.
Computer arithmetic is limited
Consider the following operation:
(3.2317006071311 * 10e616) / (3.2317006071311 * 10e616); // NaN
As Wikipedia states, computer arithmetic cannot directly operate on real numbers, but only on a finite subset of rational numbers, limited by the number of bits used to store them. In ordinary arithmetic, 3.2317006071311 * 10616 is a real finite number, but, by ECMAScript standards, it is simply too large (i.e, considerably greater than Number.MAX_VALUE), and is therefore represented as Infinity. Attempting to divide an infinity by an infinity yields NaN. Of course, in ordinary arithmetic, since both operands are finite, the operation clearly equals 1.
In this case, the NaN is in place of a real number that it could not compute (i.e, 1) due to the size of the operands. It would seem counter-intuitive if typeof NaN were to return something other than "number". After all, in this example, NaN simply represents a value which could not be determined by computer arithmetic.
NaN is unordered
According to the IEEE 754 floating-point standard, comparison with NaN always returns an unordered result. That is, NaN is not equal to, greater than, or less than anything, including itself:
NaN < 1; // false
NaN > 1; // false
NaN == NaN; // false
// But we can still check for NaN:
isNaN(NaN); // true
This is why you cannot determine whether a given value is NaN by comparing it to NaN, and instead you must use the isNaN() function.
It is not surprising, then, that the native implementation of the function isNaN() could be simply replaced with:
// Native implementation
function isNaN(x) {
// Coerce into number
x = Number(x);
// if x is NaN, NaN != NaN is true, otherwise it's false
return x != x;
}
Of course, I wouldn’t recommend replacing the native implementation. However, there are some libraries out there which introduce their own. For example, Underscore’s implementation is as follows:
_.isNaN = function(obj) {
// `NaN` is the only value for which `===` is not reflexive.
return obj !== obj;
};
But, its behavior is not same as the native isNaN() function:
var x; // undefined
isNaN(x); // true
isNaN(undefined); // true
isNaN("a"); // true
compared to Underscore’s:
var x; // undefined
_.isNaN(x); // false
_.isNaN(undefined); // false
_.isNaN("a"); // false
I can’t be certain, but I suppose Underscore included this implementation because you might be interested in checking that the value is indeed NaN, since the only value that satisfies an unequality check against itself is NaN.
Booleans are NOT NaNs
Consider the following code:
isNaN(true); // false
isNaN(false); // false
This is because booleans are considered and implemented as numerical values with a single binary digit (i.e., bit), thus they are coerced into their respective bit representations:
Number(true); // 1
Number(false); // 0
Resources
- ECMAScript Language Specification - NaN
- MDN - NaN
- Wikipedia - NaN
- Wikipedia - Indeterminate Forms
- Wikipedia - Real number
- Wikipedia - IEEE floating point
- IEEE Standard 754 Floating Point Numbers
Subscribe to the RSS feed