All three are ordinary Number values (typeof NaN is "number") that the IEEE 754 binary64 format reserves for results that aren't a normal finite number.
NaN("not a number") is the result of an invalid operation:0 / 0,Math.sqrt(-1),Infinity - Infinity,Number('abc'). It is the only JavaScript value for whichx !== x, and every comparison with it isfalse, sox === NaNcan never work. Test withNumber.isNaN(x), which does no coercion. The globalisNaNcoerces first, soisNaN('foo')istrue.-0is a second zero with the sign bit set. It comes from things like-1 * 0,Math.round(-0.4)or-0itself.0 === -0istrue, andString(-0)is"0", so it is easy to miss.Object.is(x, -0)detects it, and1 / xis-Infinityfor it.Infinity/-Infinityresult from overflow or from dividing a non-zero number by±0.1 / 0isInfinity;1 / -0is-Infinity. Test withNumber.isFinite(x), which isfalseforNaNand both infinities and does no coercion.
Which equality sees what:
NaN vs NaN |
0 vs -0 |
|
|---|---|---|
===, indexOf |
not equal | equal |
Object.is (SameValue) |
equal | not equal |
includes, Set, Map (SameValueZero) |
equal | equal |