我们都知道在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两个显著的特点:
- 任何与NaN的操作都会返回NaN
- 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即可。