NaN 是一个全局对象的属性(和 Number.NaN
的值一样),表示不是一个数字(Not-A-Number)。
NaN 的产生
以下场景下都有可能产生 NaN
值:
- 不定式
0/0;
Infinity/Infinity;
0 * Infinity;
Infinity - Infinity;
Math.pow(1, Infinity);
- 产生复数结果的运算
// 负数开偶次方
Math.sqrt(-1);
- 类型转换
'a' - 1;
undefined - 1;
parseInt('a1');
parseFloat('a1');
这里需要注意 parseInt()
和 parseFloat()
的特殊性,与 Number()
的整体转换不同,这两者只转换第一个无效字符之前的字符。
parseInt('1a'); // 1
parseInt('a1'); // NaN
isNaN()
日常编码中很少会直接操作 NaN
值,一般会在数值运算出现异常时出现,那么我们如何判断一个值是否为 NaN
呢?
NaN == NaN; // false
NaN === NaN; // false
可怕!NaN
自身居然不等于自身(这也是 JS 值中唯一一个如此特殊的)。所以等号运算符是不能正确判断的,只能通过 isNaN() 函数。
然而,isNaN()
函数也并不如其名 —— 判断是否为(数字类型下的)非法数字,更准确的说是 判断一个值在转换成数字类型后是否为非法数字:
isNaN('1'); // 1
isNaN([]); // 0
isNaN(false); // 0
这是因为,如果 isNaN()
函数的参数不是 Number
类型, isNaN
函数会首先尝试将这个参数转换为数字类型,然后才会对转换后的结果是否是 NaN
进行判断。
这里收集了一些特殊值在转换为数字类型和 NaN
判断时的表现。除了 Number()
和 isNaN()
函数在不传参数的情况下有差异之外,其他表现都是符合预期的。
参数 | Number | isNaN |
---|---|---|
0 | true | |
undefined | NaN | true |
null | 0 | false |
true | 1 | false |
false | 0 | false |
'' | 0 | false |
{} | NaN | true |
[] | 0 | false |
[1] | 1 | false |
[1, 2] | NaN | true |
但我们可以通过预判断参数是否为数字类型来优化 isNaN
函数:
var _isNaN = function(v) {
return typeof v === 'number' && isNaN(v);
}
Number.isNaN()
ES6 提供了 Number.isNaN() 函数,不会强制将参数转换为字。也就是说,只有在参数为数字类型且值为 NaN
时才会返回 true
。
Number.isNaN(null); // false
Number.isNaN('1'); // false
网友评论