I was on a video streaming site recently and moved the play point to the far right. It was amusing to see the hover details show *NaN:NaN* – ahah, some mathematical operation had *NaN-ed* and the code didn’t cater for that.

If you have read Why JavaScript ‘seems’ to get addition wrong; you would have seen that some operations do result in a *NaN*. *NaN* is a value with its roots in the IEEE754 standard definition.

**What is NaN?**

Nan literally means *Not a Number.* Yes, it means that value is not a number and occurs when you try to coerce a non-mathematical value (e.g. string) into a number.

**How do you check if a value is NaN**

How do you know if some value is *NaN*? Turns out this is not so straightforward.

For numbers, we typically compare to the expected value and that is usually *true; *however the case for *NaN* is different.

```
let two = 2;
two === 2; // true
two == 2; // true
// NaN
let x = NaN;
x === NaN; // false
x == NaN; // false
x === x; // false ???
```

**Unequal ‘equalities’ in Maths and JavaScript**

You might be scratching your head and wondering if there are other values that can be unequal. Yes, there is one – Infinity. In Mathematics, infinite values are not equal even if most operations assume this for simplicity.

Imagine two containers of water – a large jug and a small cup. Both contain infinite amounts of atoms right? Yet, it is obvious that the infinite amount of atoms in the large jug is **greater** than the infinite amount of atoms present in the small cup. The inability to determine a specific value doesn’t automatically make all infinite values equal.

Thus, even though the result of 1 * ∞ and 10 * ∞ are both ∞ in most languages; we can argue the latter is a ‘larger’ type of ∞. It might not matter so much given that computers have finite storage limits. For a more in-depth discussion of this, read Jeremy Kun’s excellent post.

Let’s see if JavaScript obeys this Maths law.

```
let infinity = Infinity;
infinity === Infinity; // true
(2 * Infinity) === (10 * Infinity); // true
```

So JavaScript coalesces all Infinity values and makes them ‘equal’. But *NaN* is exempt from this as shown earlier.

The good thing is that this special quality of *NaN* stands out. According to the IEEE754 standard, *NaN *cannot be *equal* to anything (even itself). Thus to determine if a value is *NaN,* you can check if that value is not equal to itself.

```
let nan = NaN;
nan === nan; // false
nan !== nan; // true
```

**The Issue with JavaScript’s isNaN** method

JavaScript exposes the *isNaN *method for checking for *NaN* values. The snag however is that it behaves unreliably with varying operand types.

```
isNaN(NaN); // true
isNaN(2); // false
isNaN('a'); // true
isNaN(); // true
isNaN(null); // false
isNaN(true); // false
```

Surprised? Again, this is the exhibition of one of JavaScript’s quirks. The spec reads thus:

Returns true if the argument coerces to NaN, and otherwise returns false.

And what’s the *toNumber *coercion table?

Value | Numeric value |
---|---|

null | 0 |

undefined | NaN |

true | 1 |

false | 0 |

123 | 123 |

[] | 0 |

{} | NaN |

So you now know why *isNaN() *and *isNaN({a: 1}) *are both *true *even though *isNaN([]) *is false. Even though arrays are objects, their *toNumber* coercion is not *NaN (*as shown in the table above). Similarly since the boolean primitives coerce to numbers; calling *isNaN(true) *or *isNaN(false)* will give a *false *outcome.

**Reliably verifying NaN values**

There are two fixes to this

### 1. PolyFill (isReliablyNaN)

Prior to ES6, the only way is to check if the value is not equal to itself.

```
function isReliablyNaN(x) {
return x !== x;
}
```

### 2. Number.isNaN method in ES6

ES6 introduces the *Number.isNaN* method which avoids the inherent *toNumber *coercion of *isNaN***. **This ensures that only *NaN* returns true.

```
Number.isNaN(NaN); // true
// All work as expected now
Number.isNaN(2); // false
Number. isNaN('a'); // false
Number. isNaN(); // false
Number. isNaN(null); // false
Number.isNaN(true); // false
```

**Conclusion**

If you are using *isNaN* in your code; you most likely have a bug waiting to happen some day some time.

You should switch to *Number.isNaN *which is already supported by all major browsers except IE11 and also add a polyfill fallback (just in case). You should also know that *isFinite* uses *isNaN *internally and consequently suffers the same flaws. Use *Number.isFinite* instead.

I would have wanted a reliable *isNaN *implementation but alas the special characteristic has now become a ‘feature’ and can’t even be fixed for backwards compatibility reasons.

**Related**

If you enjoyed this post and wanted to learn more; here are a couple of posts explaining various quirky behaviours in JavaScript.

Infinite amount of atoms? Not true

LikeLike

Yes, uncountably infinite

LikeLike