Codementor Events

NaN, isNaN() & Number.isNaN()

Published Sep 20, 2020Last updated Mar 18, 2021
NaN, isNaN() & Number.isNaN()

The number type has several special values, and one of them is NaN.

In this article I am going to share some of the things we need to be aware of when working with this special value.

I suggest you try the code snippets as you find them along the article.

The naming is confusing

Let's do a typeof on NaN to see what it returns:

typeof NaN  // "number"

As you can see it returns "number" as the type, so it clearly means that NaN is actually a number... wait a second, what!? 😮

So, it would have been better to name this special value something like: "Not a Valid Number" or similar, in order to avoid the confusion.

The NaN special value represents some sort of error in the number set. It is returned when we try to do a mathematic operation and it fails. So, In this case, the NaN special value is returned.

The equality quirk

If we want to check if some value stored in a variable is NaN, using either the === or the == operators won't work since NaN is the only value that is not equal to itself.

const x = 10 / "foo"

x === NaN    // false
x == NaN     // false

NaN !== NaN  // true

Checking if a value is NaN

There are two methods that can help us testing if a value is NaN. We can use either the built-in global utility method isNaN() or the Number.isNaN() utility. But you will see bellow why is recommended to always use Number.isNaN() instead of isNaN(). Let's try them out:

const y = Math.sqrt(-1)
const z = "bar"

isNaN(y)   // true
isNaN(z)   // true
isNaN(20)  // false
isNaN("55")// false

It seems that the isNaN() utility is taking the NaN literally as Not a Number.

Let's thinkg about it for a moment... 🤔

It seems the isNaN() logic is somethimg like this:
"If the value passed is (or evaluates to) either the special value NaN or something that is not of the type number ( typeof x !== "number" ), then return true"

However, this is clearly not accurate, because, as far as we know typeof NaN === "number", so it should return true only if we pass something that is (or evaluates to) the special value NaN, and it should return false if the value is not of type of number.

Let me elaborate a bit more on this.

The logic should be instead something like this:
"If the value passed is literally the value NaN return true, otherwise return false".

Fortunately, there's a utility method (a replacement of isNaN) that does exactly that:

const a = 20 / "foo"
const b = "bar"
const c = 35
const d = {}

Number.isNaN(a)   // true
Number.isNaN(b)   // false
Number.isNaN(c)   // false
Number.isNaN(d)   // false

If you want to check the browser support for this built-in utility method, you can go to Can I Use: Number.isNaN.

However, it has a 94.06% global support, so nothing to worry about here. IE doesn't support it, but it is almost gone anyway.

A couple of polyfills for Number.isNaN

Writing these polyfills will help us understand these utilities a bit more.

if(!Number.isNaN) {
  Number.isNaN = function(n) {
    if( typeof n === "number" ) {
      return window.isNaN(n)
    } 
    return false
  }
}

So in this one, we filter the value and make sure it has the type of number, if so we use the isNaN utility.

But we can use an even simpler solution, considering the fact that NaN is not equal to itself. Let's see:

if(!Number.isNaN) {
  Number.isNaN = function(n) {
    return n !== n
  }
}

Extra

We can also use the Object.is() method to check if two values are the same. It is helpfull because it covers even the corner cases like -0 === 0 // true (which should be false in this particular case) and it covers the NaN equality quirk as well.

Object.is(NaN, NaN)  // true

If you want to learn more about Object.is you can go to this MDN link.

Discover and read more posts from Diego Palacios Lepore
get started
post comments2Replies
Farai Tanekha
4 years ago

Nice breakdown Diego. I wouldn’t say i’m new to the world of programming (Js mainly), but there has always been few concepts that I have had a difficult time trying to get my nogging around, or at least have never quite felt like I understand them fully. It makes me uncomfortable. So i have to learn more. Thanks, i enjoyed your post. Perhaps next time you can try tackling ‘null’ ? How’s that for a challenge :)

Diego Palacios Lepore
4 years ago

I’m glad you find it helpful Farai! I agree, some concepts aren’t easy to grasp at first in JS.

And regarding ‘null’: challenge accepted 🙂, I’ll add that to my in-progress posts list.