Why does [NaN].includes(NaN) return true in JavaScript?

Yossi Vainshtein picture Yossi Vainshtein · Mar 22, 2021 · Viewed 9.4k times · Source

I'm familiar with NaN being "weird" in JavaScript, i.e., NaN === NaN always returns false, as described here. So one should not make === comparisons to check for NaN, but use isNaN(..) instead.

So I was surprised to discover that

> [NaN].includes(NaN)
true

This seems inconsistent. Why have this behavior?

How does it even work? Does the includes method specifically check isNaN?

Answer

Nguyễn Văn Phong picture Nguyễn Văn Phong · Mar 22, 2021

According to MDN's document say that

Note: Technically speaking, includes() uses the sameValueZero algorithm to determine whether the given element is found.

const x = NaN, y = NaN;
console.log(x == y); // false                -> using ‘loose’ equality
console.log(x === y); // false               -> using ‘strict’ equality
console.log([x].indexOf(y)); // -1 (false)   -> using ‘strict’ equality
console.log(Object.is(x, y)); // true        -> using ‘Same-value’ equality
console.log([x].includes(y)); // true        -> using ‘Same-value-zero’ equality


More detailed explanation:

  1. Same-value-zero equality similar to same-value equality, but +0 and −0 are considered equal.
  2. Same-value equality is provided by the Object.is() method: The only difference between Object.is() and === is in their treatment of signed zeroes and NaNs.

enter image description here


Additional resources: