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:

  1. Division of zero by zero
  2. Dividing an infinity by an infinity
  3. Multiplication of an infinity by a zero
  4. Any operation in which NaN is an operand
  5. Converting a non-numeric string or undefined into 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

  1. ECMAScript Language Specification - NaN
  2. MDN - NaN
  3. Wikipedia - NaN
  4. Wikipedia - Indeterminate Forms
  5. Wikipedia - Real number
  6. Wikipedia - IEEE floating point
  7. IEEE Standard 754 Floating Point Numbers