Skip to content

Demystifying isNaN and Number.isNaN in JavaScript

NaN (“Not a Number”) in Javascript looks like an error value, but it’s actually a number. It compares unequal to itself. It has two competing functions to detect it: the global isNaN() and the newer Number.isNaN().

As developers, we can’t treat this as trivia. Data validation, numeric pipelines, and type safety all depend on knowing exactly which one to use.


1. A Little History

When JavaScript was created in 1995, the global function isNaN() was added. The idea was simple: check if something is NaN. But there was a twist: it first coerces the input into a number.

js
isNaN("123");    // false - coerces "123" into 123
isNaN("abc");    // true  - coerces "abc" into NaN
isNaN(undefined);// true  -  coerces undefined into NaN
isNaN("");       // false - coerces "" into 0

Coercion

That coercion made sense for form inputs in the early web. But in modern applications, it’s dangerous: empty strings and undefined suddenly look like “valid” numbers. ECMAScript 2015 (ES6) introduced Number.isNaN() as the strict, no-coercion alternative.

2. What Exactly Does Number.isNaN Do?

Number.isNaN(value) asks one—and only one—question: 👉 “Is this value literally the special NaN number?”

That means:

js
Number.isNaN(NaN);        // true
Number.isNaN(56);         // false → valid number
Number.isNaN("56");       // false → string, not NaN
Number.isNaN("abc");      // false → string, not NaN
Number.isNaN(undefined);  // false → not NaN

Note how;

  • You know the data you are dealing with like With isNaN("abc"), you’d get true (because coercion turns "abc" to NaN), which can mislead you into thinking "abc" is “already” NaN.
  • It separates type-checking from numeric validation
    • Number.isNaN answers: “Is this value literally NaN?”
    • Parsing (Number() / parseInt) answers: “Can this value become a number?”
  • It avoids false positives with isNaN("") // false, you get 0 — misleading, with isNaN(undefined) // true, you get NaN — misleading.

3. But wait... NaN === NaN

js
NaN === NaN; // false

NaN is the only value in JavaScript that is not equal to itself.NaN represents “an unrepresentable result,” and by definition, such results can never be equal.

This means:

  • 0/0 - NaN
  • Math.sqrt(-1) - NaN
  • parseInt("xyz") - NaN

comparing them

js
0/0 === Math.sqrt(-1); // false

4. Example: Input Validation

If we had a checkout form:

js
const form = {
  price: "199",
  discount: "abc", // user error
  tax: ""          // left blank
};

if we used isNaN

js
isNaN(form.discount); // true  → coerced into NaN
isNaN(form.tax);      // false → coerced "" into 0

That empty tax field passes validation and silently becomes 0. Dangerous.

with Number.isNaN

js
Number.isNaN(form.discount); // false → it's a string, not NaN
Number.isNaN(form.tax);      // false → also a string, not NaN

Both are safe but aren't they invalid? That is why we need parsing.

5. Parsing + Number.isNaN:

The modern way would be:

  • Parse user input with Number() (or parseFloat/parseInt if appropriate).
  • Use Number.isNaN to check if the result is valid.
js
const safeNumber = input => {
  const n = Number(input);
  return Number.isNaN(n) ? null : n;
};

safeNumber("199"); // 199
safeNumber("abc"); // null
safeNumber("");    // null

now our form is safely validated

js
const processed = {
  price: safeNumber(form.price),   // 199
  discount: safeNumber(form.discount), // null
  tax: safeNumber(form.tax)        // null
};

7. Why this matters in production

  • Silent bugs: Empty strings ("") become 0 under isNaN.
  • Loose assumptions: undefined becomes NaN when coerced.
  • Math safety: Once NaN gets into your pipeline, every operation downstream becomes NaN.
js
const subtotal = Number("199");
const discount = Number("abc"); // NaN
console.log(subtotal - discount); // NaN

8. Alternatives ways to look at it

Since NaN is the only value unequal to itself: we can do

js
const isReallyNaN = x => x !== x;

isReallyNaN(NaN); // true

Or use ES6’s Object.is, which handles it more elegantly:

js
Object.is(NaN, NaN); // true

javascript book

If this interested you, check out my Javascript Book

Enjoy every byte.