How JavaScript Treats NaN Equality Comparisons

In JavaScript, NaN (Not-a-Number) exhibits a unique behavior where it is never equal to any value, including itself, when evaluated with standard equality operators. Regardless of whether you use the loose equality operator (==) or the strict equality operator (===), any direct comparison involving NaN will return false. This article explains the specification behind this behavior, demonstrates how equality operators handle NaN, and details the correct methods to check for NaN values reliably.

The Behavior of Equality Operators with NaN

When comparing NaN to any value using either loose (==) or strict (===) equality, the result is always false:

console.log(NaN == NaN);        // false
console.log(NaN === NaN);       // false
console.log(NaN == 0);          // false
console.log(NaN === undefined);  // false
console.log(NaN == false);      // false

Conversely, the inequality operators (!= and !==) will always evaluate to true when comparing NaN to anything, including another NaN:

console.log(NaN != NaN);        // true
console.log(NaN !== NaN);       // true

Why NaN Is Not Equal to NaN

JavaScript adheres to the IEEE 754 floating-point standard for representing numbers. Under this standard, NaN does not represent a specific, distinct numeric value; rather, it signifies an undefined, unrepresentable, or erroneous mathematical result (such as 0 / 0 or Math.sqrt(-1)).

Because two distinct invalid operations do not necessarily yield the same underlying mathematical condition, the IEEE 754 specification explicitly dictates that NaN must compare unequal to all values, including itself.

How to Correctly Check for NaN

Because standard equality checks fail to identify NaN, JavaScript provides specialized methods for detection.

Introduced in ECMAScript 2015 (ES6), Number.isNaN() is the most robust way to check for NaN. It returns true only if the passed value is both of the type Number and evaluates to NaN, without performing implicit type coercion.

Number.isNaN(NaN);          // true
Number.isNaN("hello");      // false (string, not coerced)
Number.isNaN(undefined);    // false

2. Object.is()

The Object.is() method determines whether two values are the same value. Unlike ===, it treats NaN as equal to NaN.

Object.is(NaN, NaN);        // true
Object.is(NaN, 0);          // false

3. The Self-Comparison Trick

Because NaN is the only value in JavaScript that is not equal to itself, you can verify if a variable is NaN using strict inequality against itself:

function isValueNaN(val) {
    return val !== val;
}

console.log(isValueNaN(NaN));     // true
console.log(isValueNaN(123));     // false
console.log(isValueNaN("text"));  // false

4. Global isNaN() (Use with Caution)

The global isNaN() function checks if a value is NaN, but it first coerces the argument to a number. This can produce false positives for non-numeric values that cannot be parsed into numbers.

isNaN(NaN);       // true
isNaN("text");    // true (coerced to NaN, often unintended)
isNaN(undefined); // true (coerced to NaN)
isNaN("123");     // false (coerced to 123)