The Curious Case of NaN: When Numbers Stop Making Sense
In the world of JavaScript, there’s one value that consistently surprises both beginners and seasoned developers alike: NaN
. At first glance, it might look like just another value in the Number
type. But dig a little deeper, and you’ll realize it’s anything but ordinary.
Let’s start with something that baffles almost everyone:
console.log(NaN === NaN); // false
Wait, what?
How can something not be equal to itself? In every other case in JavaScript, if x === x
, it’s true — but NaN
breaks that logic.
Why Is NaN Not Equal to Itself?
This isn’t just JavaScript being weird — it’s actually by design, based on the IEEE 754 floating-point standard. JavaScript uses this standard to represent numbers, and in that world:
"NaN is not equal to anything, including itself."
This is because NaN
represents an invalid or unrepresentable number. For instance:
0 / 0
Math.sqrt(-1)
parseInt("not-a-number")
All produce NaN
.
Imagine trying to compare two invalid results — should they be equal just because both are invalid? IEEE 754 says no. So JavaScript follows suit.
Then How Do You Check for NaN?
You can't rely on strict or loose equality (===
or ==
). Instead, JavaScript gives us a better tool:
Number.isNaN(value); // ✅ Accurate
This function only returns true if the value is actually NaN, and not just some weird coercion like this:
isNaN("abc"); // true (⚠️ misleading)
Number.isNaN("abc"); // false (✅ correct)
So: Always use Number.isNaN
for reliability.
But Why is typeof NaN === "number"
?
This confuses a lot of people too. If it’s "Not a Number", why is it a number?
Well, NaN
is a numeric value, just a special one. It’s still of type "number"
, because it’s the result of an operation that should yield a number, but failed.
Think of it as:
"It's supposed to be a number, but something went wrong."
It’s like trying to divide by zero and getting a result that’s... well, undefined in math terms.
Real-World Pitfalls of NaN
One of the dangerous aspects of NaN
is how it silently breaks logic when not handled properly.
Example: Average Calculator
function average(scores) {
const sum = scores.reduce((a, b) => a + b, 0);
return sum / scores.length;
}
average([]); // NaN — because 0 / 0
That may propagate and cause downstream bugs if you forget to check.
Example: Filtering NaN Values
const data = [10, NaN, 15, NaN];
const clean = data.filter(n => !Number.isNaN(n)); // [10, 15]
What About Object.is?
Here’s another lesser-known tip:
Object.is(NaN, NaN); // true
This method can distinguish NaN
properly. It’s often used in polyfills or deep equality checks.
In Summary
NaN === NaN
is false because of IEEE 754 — it’s by design.- Use
Number.isNaN
, notisNaN
, to check for trueNaN
. typeof NaN === "number"
because it is a numeric type — just an invalid one.- Use
Object.is
if you really want to compare twoNaN
values. - Always guard against
NaN
in mathematical logic to avoid silent bugs.
Finally
In a language as quirky as JavaScript, NaN
is a reminder that not all "numbers" behave like numbers. It's a symbol of failure in numeric computation — but understanding it helps you write safer, more robust code.
Comments ()