NaN in JavaScript
NaN
, which stands for "Not a Number", is a value that JavaScript returns from certain functions and operations
when the result should be a number, but the result is not defined or not representable as a number. For example:
parseInt()
returnsNaN
if parsing failed:parseInt('bad', 10)
Math.sqrt()
returnsNaN
if the given value is negative:Math.sqrt(-1)
- Math operators return
NaN
when one of the operands isn't a number:2 * NaN
,3 ** undefined
,4 / 'foo'
, etc. The exception is+
, which JavaScript may treat as string concatenation.
Checking for NaN
The biggest quirk of NaN
is that the ===
operator says that NaN
is not equal to itself:
NaN === NaN; // false
To check if a value is NaN
, you should use the Number.isNaN()
function:
Number.isNaN(NaN); // true
Number.isNaN('test'); // false
You should not use the legacy global function isNaN()
. This function checks if the given value would
result in NaN
if you tried to convert it to a number, which can lead to surprising behavior:
isNaN(NaN); // true
isNaN('test'); // true
Be careful when using the typeof
operator with NaN
: the typeof
operator reports that NaN
is a number!
const v = parseInt('bad', 10);
v; // NaN
typeof v; // "number"
Serializing
One of the major reasons to avoid NaN
is that most serializers don't have good support for NaN
.
For example, NaN
is not representable in JSON. The JSON.stringify()
function converts NaN
into null
:
const obj = { x: NaN };
JSON.stringify(obj); // '{"x":null}'
On the other hand, Mongoose validation throws an error when a numeric value is NaN
:
const Model = mongoose.model('Test', Schema({ test: Number }));
// Throws 'Cast to Number failed for value "NaN" at path "test"'
const doc = await Model.create({ test: NaN });
In general, you should consider encountering NaN
an error unless you have a good reason not to. Writing NaN
to a database or in an HTTP request usually ends up either causing an error or ending up as a null
value.