I wanted to write something about NaN because this occupies a weird space in JavaScript and might not behave like you suspect it should when doing equality comparisons. It also came up recently, and I want to make absolutely certain that I don’t forget the manner in which I should handle this thing.
My first stop to understand something like this is the Specification! Often, this won’t necessarily explain everything I’m interested in, but it sure provides direction for further inquiry. Apparently, there are a handful of values that are “Not-a-Number” – only 9,007,199,254,740,990 according to the specification. For our purposes, as JavaScript enthusiasts, all of these are represented by a single “NaN” value.
We can also see, from the various operations on numbers in the specification, that there are a bunch of operations that might result in that special value. This means, of course, that you should figure out how to handle that value in your code if you suspect there’s even a whiff of a chance that you may encounter it. For instance, maybe you’re developing a robust suite of automated tests and you want to make sure you’ve really nailed those corner-case situations.
In that case, you need to know how this NaN is going to behave when subjecting it to the rigors of comparison – it may not work quite like you’d expect. As you can see, you’ll have to use either isNaN() or Number.isNaN(), and keep in mind the difference between the two, as highlighted by the previous link. You did check that out, right?
Perhaps the most interesting thing to me is that it behaves according to those special rules even after assignment to a variable. I had assumed (wrongly!) that it may behave like a Symbol:
const fancySymbol = Symbol(“fancy”);
fancySymbol === fancySymbol; //true
But instead, we have this behavior!
const fancyNan = NaN;
fancyNan === fancyNan; //false
It’s a small thing, and I didn’t see that as an example, specifically. I don’t know that it would matter that much, but it sure is interesting!