NaN
BaselineWidely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
TheNaN
global property is a value representing Not-A-Number.
Try it
function sanitize(x) { if (isNaN(x)) { return NaN; } return x;}console.log(sanitize("1"));// Expected output: "1"console.log(sanitize("NotANumber"));// Expected output: NaN
Value
The same number value asNumber.NaN
.
Property attributes ofNaN | |
---|---|
Writable | no |
Enumerable | no |
Configurable | no |
Description
NaN
is a property of theglobal object. In other words, it is a variable in global scope.
In modern browsers,NaN
is a non-configurable, non-writable property. Even when this is not the case, avoid overriding it.
There are five different types of operations that returnNaN
:
- Failed number conversion (e.g., explicit ones like
parseInt("blabla")
,Number(undefined)
, or implicit ones likeMath.abs(undefined)
) - Math operation where the result is not a real number (e.g.,
Math.sqrt(-1)
) - Indeterminate form (e.g.,
0 * Infinity
,1 ** Infinity
,Infinity / Infinity
,Infinity - Infinity
) - A method or expression whose operand is or gets coerced to
NaN
(e.g.,7 ** NaN
,7 * "blabla"
) — this meansNaN
is contagious - Other cases where an invalid value is to be represented as a number (e.g., an invalidDate
new Date("blabla").getTime()
,"".charCodeAt(1)
)
NaN
and its behaviors are not invented by JavaScript. Its semantics in floating point arithmetic (including thatNaN !== NaN
) are specified byIEEE 754.NaN
's behaviors include:
- If
NaN
is involved in a mathematical operation (but notbitwise operations), the result is usually alsoNaN
. (Seecounter-example below.) - When
NaN
is one of the operands of any relational comparison (>
,<
,>=
,<=
), the result is alwaysfalse
. NaN
compares unequal (via==
,!=
,===
, and!==
) to any other value — including to anotherNaN
value.
NaN
is also one of thefalsy values in JavaScript.
Examples
Testing against NaN
To tell if a value isNaN
, useNumber.isNaN()
orisNaN()
to most clearly determine whether a value isNaN
— or, sinceNaN
is the only value that compares unequal to itself, you can perform a self-comparison likex !== x
.
NaN === NaN; // falseNumber.NaN === NaN; // falseisNaN(NaN); // trueisNaN(Number.NaN); // trueNumber.isNaN(NaN); // truefunction valueIsNaN(v) { return v !== v;}valueIsNaN(1); // falsevalueIsNaN(NaN); // truevalueIsNaN(Number.NaN); // true
However, do note the difference betweenisNaN()
andNumber.isNaN()
: the former will returntrue
if the value is currentlyNaN
, or if it is going to beNaN
after it is coerced to a number, while the latter will returntrue
only if the value is currentlyNaN
:
isNaN("hello world"); // trueNumber.isNaN("hello world"); // false
For the same reason, using a BigInt value will throw an error withisNaN()
and not withNumber.isNaN()
:
isNaN(1n); // TypeError: Conversion from 'BigInt' to 'number' is not allowed.Number.isNaN(1n); // false
Additionally, some array methods cannot findNaN
, while others can. Namely, the index-finding ones (indexOf()
,lastIndexOf()
) cannot findNaN
, while the value-finding ones (includes()
) can:
const arr = [2, 4, NaN, 12];arr.indexOf(NaN); // -1arr.includes(NaN); // true// Methods accepting a properly defined predicate can always find NaNarr.findIndex((n) => Number.isNaN(n)); // 2
For more information aboutNaN
and its comparison, seeEquality comparison and sameness.
Observably distinct NaN values
It's possible to produce two floating point numbers with different binary representations but are bothNaN
, because inIEEE 754 encoding, any floating point number with exponent0x7ff
and a non-zero mantissa isNaN
. In JavaScript, you can do bit-level manipulation usingtyped arrays.
const f2b = (x) => new Uint8Array(new Float64Array([x]).buffer);const b2f = (x) => new Float64Array(x.buffer)[0];// Get a byte representation of NaNconst n = f2b(NaN);const m = f2b(NaN);// Change the sign bit, which doesn't matter for NaNn[7] += 2 ** 7;// n[0] += 2**7; for big endian processorsconst nan2 = b2f(n);console.log(nan2); // NaNconsole.log(Object.is(nan2, NaN)); // trueconsole.log(f2b(NaN)); // Uint8Array(8) [0, 0, 0, 0, 0, 0, 248, 127]console.log(f2b(nan2)); // Uint8Array(8) [0, 0, 0, 0, 0, 0, 248, 255]// Change the first bit, which is the least significant bit of the mantissa and doesn't matter for NaNm[0] = 1;// m[7] = 1; for big endian processorsconst nan3 = b2f(m);console.log(nan3); // NaNconsole.log(Object.is(nan3, NaN)); // trueconsole.log(f2b(NaN)); // Uint8Array(8) [0, 0, 0, 0, 0, 0, 248, 127]console.log(f2b(nan3)); // Uint8Array(8) [1, 0, 0, 0, 0, 0, 248, 127]
Silently escaping NaN
NaN
propagates through mathematical operations, so it's usually sufficient to test forNaN
once at the end of calculation to detect error conditions. The only case whereNaN
gets silently escaped is when usingexponentiation with an exponent of0
, which immediately returns1
without testing the base's value.
NaN ** 0 === 1; // true
Specifications
Specification |
---|
ECMAScript® 2026 Language Specification # sec-value-properties-of-the-global-object-nan |