Check out a free preview of the full Deep JavaScript Foundations, v3 course

The "NaN & isNaN" Lesson is part of the full, Deep JavaScript Foundations, v3 course featured in this preview video. Here's what you'd learn in this lesson:

Kyle discusses what a NaN, how to use isNaN, and common sources of error in the usage of both.


Transcript from the "NaN & isNaN" Lesson

>> Kyle: Within those primitive types there are special values that we should pay attention to. And there are a number of them but I wanna focus our attention on two specific special values. These are ones that crop up much more often than we would like, or at least some of them, at least one of them crops up more often than we would like.

And awareness of both of them is gonna help us avoid bugs and in some cases, even get more power out of our JavaScript language. So let's look at the first one it's referred to as NaN, which is supposedly an acronym for not a number. Historically, that's where it comes from, NaN comes to us at least in JavaScript, it comes by way of the IEEE 754 spec, the number spec.

Essentially NaN doesn't mean not a number essentially it means this special what we call sentinel value that indicates an invalid number. That's a much better mental model for it than referring to it is not a number, we oughta refer to at as an invalid number, so let's dig into that.

How do we arrive at something like a Nan? Well, number one, you can take things that are representations of numbers in string form, in this case. Like for example, my age at the moment is 38, and I can represent that either as quote 38 or, in this case, on line 1, I could represent it in octal.

The octal representation being 46. I don't like that one, cuz that makes me sound a lot older so I don't wanna use that. But I can represent it in string form, and then I have a number, like the number 38. Or I can do quote 39 to reference my next age.

I don't own cats anymore, so when I say my cat's age, and I use something like not applicable there's no number to use to refer to that. And let me be very specific and clear with you the number 0 is not the way you indicate the absence of valid numeric value.

Talk to any math mathematician, the number 0 is absolutely an important number. It is a number that has substance to it. It's not appropriate in any way shape or form to think of 0 as being the place holder for absence of numeric value. Doesn't make sense mathematically and doesn't make sense programatically.

So what number should we use? Well, that's why IEEE did when they defined the special bit pattern that represents this is the number that we indicate. It's not a valid number, I can't do anything with n/a. There's essentially no number system where n/a is a valid representation of a number [LAUGH] unless you invented one.

So we get NaN back, we get the invalid number back. And by the way, when you do things with an invalid number, even things that seem crazy, like subtracting strings, you're gonna get invalid number back. Line 4, my age minus, and then a string, like my son's age, doesn't actually make any sense, not programatically, anyway.

But JavaScript has a way of thinking about this that we often gloss over. In particular, JavaScript thinks about this as the minus operator needs numbers, it's only defined for numbers. When you give it something that is not a number,
>> Kyle: Then it says, I need to turn it into a number.

That's what we'll talk about when we get into coercion in a little bit. So, it turns the, quote, my son's age, which by the way he's 8, my son's age, it turns his age, that string into the NaN value. So when I say my age minus, I'm actually saying my age minus NaN, and NaN with any other mathematical operation is always NaN, cuz it's invalid.

So NaN sort of propagates all the way out. There's nothing that you can ever do that includes a NaN and results in anything other than a NaN, mathematically anyway. And by the way, you'll notice that even though my cat's age is NaN, it is not equal to itself, or at least according to the triple equals operator, it's not equal to itself.

Many people like to believe that the triple equals operator tells you the truth, but I have news for you the triple equals operator lies. It tells you that those two things are not equal. And the reason it does that is not because Brendan Eich was crazy that day.

It does that because IEEE said NaNs are not equal to each other. As a matter of fact, NaN is the only value in existence, at least in JavaScript, it's the only value that does not have what we call the identity property, meaning it is not equal to itself.

It's the only value where that is true.
>> Speaker 2: Undefined, undefined's the same?
>> Kyle: Undefined is absolutely equal to itself. NaN is the only value that is not equal to itself. So we need some way to determine because triple equals lies to us, we need some way to determine if the value is in fact NaN.

And JavaScript shipped originally with a utility called isNaN, which when we pass a thing like a number to it we correctly get false. And when we pass a thing that actually, legitimately is NaN, we get true. Seems great until we look at line 10 when we pass in something that is definitely not a number, the string my son's age.

But let me ask you the question, it's not a number, we agree with that, but is it the NaN value? Most definitely not. So why do we still get true? The historical reason for getting true, is because for some reason, the isNaN utility coerces values to numbers before it checks for them to be NaN.

>> Kyle: So, it's gonna coerce the string my son's age to a number and guess what number it's gonna coerce it to? The NaN value, so of course it's gonna back true. Now, guess how I know that it does that. I read the spec, and the spec very clearly says, coerce it to a number.

Sometime after that mistake happened in initial JavaScript, they decided that's a bad idea. So with ES6, we got a better utility, the Number.isNan utility. And that Number.isNan tells us defiantly for sure it's the NaN value or it's not. In other words it doesn't do any coercion for us.

It tells us specifically it's the number. So like going back to your question about what is NaN? Well, if I do a numeric operation and I get back a value what type am I expecting back from every single numeric operation? I'm expecting a number, right? And remember I said NaNs are part of the IEEE 754 spec which is a numeric representation specification.

So perplexingly, the type of a NaN is number. It's just an invalid number. Which is why it's not appropriate to think of it as not a number because then you get into that weirdness the wording of type of not a number is number? That's because it's wrong to think of it as not a number, it's better to think of it as an invalid number.

And of course the type of and invalid number is definitely number. I have people suggest to me no no no they should have never done NaN nevermind what I EEE 754 said. They never should have done NaN, we should have returned something else. Really? What should we return from a numeric operation that's gonna be not of the type number?

We could return back undefined, but that's not numeric. That's a terrible idea, to give developers something that's a bait and switch. We could maybe return back null, terrible idea. We could return back false, terrible idea, we could return back, ugh, -1. This is old, historical, when you do something like index of, and it can't find something in your string or array.

Because in the old C days, you could only return numbers, and they weren't IEEE 754. So what was the only number they could come up with to represent didn't find it or invalid search? They chose -1, which was fine for them like 40 years ago. I don't know why we adopt it in a JavaScript but we did.

So we have some of our APIs that return back -1, when the more appropriate number that we had in the language, to represent I didn't find it as NaN. If you're designing a system, and you wanna return and somebody expects to get a number and you wanna signal to them there's no valid number for me to give there is only one value that makes any sense at all.

You should return the NaN. But more than any other complaint that I have on this list is when people try to refer to 0 as somehow a placeholder for NaN. And we'll come back to this and coercion and just a moment. So NaN, it is a number, and it is the invalid number, and it is going to occur in your programs, not maybe, it will, and you should be testing for it appropriately.

Otherwise, you have bugs and you're not handling those bugs.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now