isNaN()

Tests whether a value becomes NaN after being coerced to a number.

Signature
isNaN(value)
  • Added in JavaScript ECMAScript 1 (1997)

Parameters

ParameterTypeDescription
$valueanyThe value to be tested. It is converted to a number before the test.

Return value

booleantrue if the value is NaN after conversion to a number; otherwise false.

Errors

Throws TypeError if the value is a BigInt or a Symbol, since neither can be converted to a number.

Changelog

  • PHP ECMAScript 2015Number.isNaN() was added as the non-coercing alternative and is the preferred check in new code.

isNaN() does not answer "is this value NaN". It answers "would Number(value) be NaN", which is a different and much broader question. That is why isNaN("abc") is true even though the string "abc" is not the NaN value, and why isNaN(undefined) is true while isNaN(null) is false.

Which one you actually want

  • To detect the NaN value itself, use Number.isNaN(x), or the identity trick x !== x, which is true only for NaN.
  • To decide whether an arbitrary value parses as a number, the coercion in isNaN() is exactly what you want — but write the intent out as Number.isNaN(Number(x)) so the next reader is not left guessing.

The coercion table people trip on

Empty strings, whitespace-only strings, null, false, empty arrays and single-element numeric arrays all convert to a number cleanly, so isNaN() returns false for every one of them. Passing a BigInt or a Symbol throws a TypeError rather than returning true, which can crash a validation path that assumed the function was total.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Reject a user-entered string that does not parse as a number at all.
  • Guard an arithmetic result before writing it to a total or an average.
  • Check whether a parsed date or measurement came back as NaN before formatting it.

Frequently asked questions

Why is isNaN('abc') true when 'abc' is a string, not NaN?

Because isNaN converts its argument to a number first, and Number("abc") is NaN. Use Number.isNaN("abc"), which returns false, if you want to test for the NaN value itself.

Should I use isNaN or Number.isNaN?

Use Number.isNaN in new code — it tests for the NaN value with no coercion and never throws. Reach for the global isNaN only when you deliberately want the "does this coerce to a number" behaviour, and even then Number.isNaN(Number(x)) states it more clearly.

Why does NaN === NaN return false?

IEEE 754 defines NaN as unequal to every value including itself, so no equality operator can detect it. That is precisely why Number.isNaN, Object.is and the x !== x idiom exist.

More examples

isNaN versus Number.isNaN

Number.isNaN is true for exactly one entry — the NaN value. The global isNaN is additionally true for "NaN", undefined and {}, because those coerce to NaN.

Example · javascript
const values = [NaN, "NaN", "42", "", null, undefined, true, [], {}];

for (const v of values) {
  console.log(
    JSON.stringify(v) ?? String(v),
    "| isNaN:", isNaN(v),
    "| Number.isNaN:", Number.isNaN(v),
  );
}

Why NaN needs a function at all

Equality operators can never find NaN, so indexOf misses it while includes finds it. Object.is and x !== x are the two reliable identity checks.

Example · javascript
const x = 0 / 0;
console.log(x === NaN);        // false — NaN equals nothing, itself included
console.log(x !== x);          // true  — the classic self-inequality test
console.log(Object.is(x, NaN)); // true
console.log([NaN].includes(NaN)); // true  — includes uses SameValueZero
console.log([NaN].indexOf(NaN));  // -1    — indexOf uses ===

A validation helper that says what it means

Explicit handling of the blank-string case is what the global isNaN silently skips. The last two lines show that null still slips through as 0 unless you reject it by type as well.

Example · javascript
function toNumber(input) {
  if (typeof input === "string" && input.trim() === "") return null;
  const n = Number(input);
  return Number.isNaN(n) ? null : n;
}

console.log(toNumber("42"));   // 42
console.log(toNumber("  "));   // null — blank handled explicitly
console.log(toNumber("abc"));  // null
console.log(toNumber(null));   // null? no — Number(null) is 0
console.log(toNumber(null));   // 0

Discussion

  • Be the first to comment on this lesson.