比较isNaN()与Number.isNaN()

93 阅读3分钟

我们都知道在JavaScript中Number类型数据中存在着一个特殊的值——NaN(Not a Number),NaN的存在是为了保证程序在某些异常情况下能够继续运行,如0/0,在某些语言中会抛出异常,但是在JavaScript中会返回"NaN",程序可以正常执行。

typeof 1 / 0   // "NaN"
typeof (1 / 0)  // "number" (1/0 返回Infinity)
// 除了0/0,其他任何数除以0都会返回Infinity

NaN两个显著的特点:

  1. 任何与NaN的操作都会返回NaN
  2. NaN与任何值都不相等,即使是它本身

在ES5中,提供了isNaN()函数来判断是否是NaN;
在ES6中,给Number类型增加了一个静态方法——isNaN()来判断是否是NaN

isNaN();
Number.isNaN();

isNaN()函数

它用来确定一个变量是不是NaN

倘若给isNaN()函数传递一个Number类型的数据,很容易判断出是不是NaN。如果是非Number类型的数据,那结果又会是如何?

isNaN({}); // true

因为isNaN()会进行数据的类型转换,在处理传入的参数时判断能否转换为数字,如果可以转换成数字则会返回false;反之,则返回true

isNaN(NaN); // true
isNaN(undefined); // true
isNaN({}); // true

isNaN(true); // false
isNaN(null); // false

isNaN(new Date()) // false
isNaN(new Date().toString()) // true

Date是一种特殊的类型,当调用new Date()生成的实例并且在转换为数字类型的情况时,会转换为对应的时间戳,所以使用isNaN()函数判断时会返回false,因为它可以转换为数字。

isNaN(new Date()); // 114514(当然,这并不是有一个合法的时间戳)

当使用了toString()函数时,返回的是一串字符串表示的时间,无法转换成数值类型,因此会返回true。

Number.isNaN()函数

为什么ES6会在Number类型上增加一个静态方法isNaN()呢?
这种关系类似于Object.defineProperty()与Reflect对象,正由于Object作为一个构造函数,某些操作放到它身上有些不合适,会显得太过臃肿,所以ES6新增了Reflect,让我们将操作都集中在Reflect对象上。isNaN()和Number.isNaN()的关系与它们类似,Number.isNaN()的出现会在真正意义上去判断变量是否为NaN,且不会去做数据类型转换只有在传入的值为NaN时,才会返回true;传入其他类型时返回false

Number.isNaN(NaN); // true
Number.isNaN(undefined); // false
Number.isNaN(null); // false

兼容性处理

由于Number.isNaN()是出现在ES6中的,难免会出现兼容性问题。

// 兼容性处理
if (!Number.isNaN) {
    Number.isNaN = function(val) {
        return val !== val;
    }
}

如果一个值和自身比较,只有在该值为NaN时才会返回false,其余情况返回true

总结

  • isNaN()在判断是否是NaN时,需要先进行类型转换,只有在无法转换成数字的情况下才会返回true
  • Number.isNaN()在判断是否是NaN时,不会做类型转换,只需要判断传入的值是否是NaN即可。