How to test whether something is identically NaN?

2019-06-25 14:01发布

问题:

In Javascript:

NaN === NaN; // false

I was trying to determine when isNaN(foo) is not just equivalent to +foo "is" NaN. But I don't know how to tell if something is NaN except by using isNaN, which says yes for many things, none of which === NaN.

So I think the right way to do this would be to work around other possibilities:

typeof NaN === 'number' // true

Therefore I think

typeof(foo) === 'number' && isNaN(foo)

Is the closest to what I am thinking of. It makes sense since it makes sense that NaN would be the only number that isn't a number, or something. Is this correct, and is this the best way?

回答1:

Use that to your advantage:

foo !== foo

This is equivalent to typeof foo === 'number' && isNaN(foo), and is what Underscore.js uses to check for exactly NaN, too.



回答2:

The reason that NaN isn't equal to itself is that two calculations can become NaN for different reasons. If you do two calculations and compare the results, you don't want them to be equal if one of the values are NaN, or both of them.

The isNaN method works fine as long as you only use it on numerical values. It gives unintuitive results for a lot of other types, so you simply shouldn't use it on anything other than numbers.



回答3:

If you can use ECMAScript 6, you have Object.is:

return Object.is(foo, NaN);

Object.is() determines whether two values are the same value. Two values are the same if one of the following holds:
[...]

  • both NaN

MDN also suggests a Polyfill if Object.is isn't defined (uses the same foo!==foo trick):

if (!Object.is) {
  Object.is = function(x, y) {
    // SameValue algorithm
    if (x === y) { // Steps 1-5, 7-10
      // Steps 6.b-6.e: +0 != -0
      return x !== 0 || 1 / x === 1 / y;
    } else {
      // Step 6.a: NaN == NaN
      return x !== x && y !== y;
    }
  };
}