深入理解 JavaScript 中的 NaN
在 JavaScript 的世界里,NaN是一个颇为特殊的存在,初看它,你可能会觉得有些矛盾,明明叫 “不是一个数字(not a number)”,可typeof NaN的结果却为number。今天,咱们就来深入探究一番这个特殊的NaN。
一、NaN 的产生
NaN的诞生有多种情境:
- 一个不能被解析的数字:
当我们试图将明显不是数字格式的内容强制转换为数字时,就会得到NaN。例如:
Number('abc'); // NaN
Number(undefined); // NaN
这里,字符串'abc'和特殊值undefined都无法被正确解析成合法数字,所以结果为NaN。
- 失败的操作:
在数学运算领域,一些不合理的操作也会催生NaN。像对负数求对数(在实数范围内)、对负数求平方根(同样在实数范围内)以及求超出反余弦函数定义域的值的反余弦,都会得到这个特殊结果:
Math.log(-1); // NaN
Math.sqrt(-1); // NaN
Math.acos(2); // NaN
- 一个运算符为 NaN:
一旦参与运算的某个值是NaN,那整个运算结果大概率也是NaN。因为NaN就像一个 “黑洞”,只要碰到它,正常的数字运算规则就被打破。比如:
NaN + 1; // NaN
10 / NaN; // NaN
二、注意点
NaN有个极为独特的性质,它是 JavaScript 中唯一一个和自身不相等的值:
NaN === NaN; // false
这一点与我们常规对相等性的认知截然不同,却也是理解NaN行为的关键。
三、如何辨别 NaN
在实际编程中,常常需要判断一个值是不是NaN。JavaScript 提供了全局函数isNaN(),但它的行为有些微妙。
起初看,它似乎是用来判断一个值是不是NaN:
isNaN(NaN); // true
isNaN(10); // false
可实际上,isNaN()并非单纯判断是不是NaN这个值。它首先会尝试把传入的值转换成数字,若转换结果是NaN,函数就会返回true。这就导致对非数字的判断容易出错,例如:
isNaN('abc'); // true
所以,当我们真想确定一个值是不是NaN时,可以采用以下两种靠谱方法:
- 方法一:将 isNaN () 和 typeof 结合来判断:
function isValueNaN(value) {
return typeof value === 'number' && isNaN(value);
}
这种方式先通过typeof确认值是数字类型,再结合isNaN进一步判断,避免了非数字值的误判。
- 方法二:值是否与本身不相等(NaN 是唯一有这样特征的值) :
function isValueNaN(value) {
return value!== value;
}
巧妙利用了NaN与自身不相等的特性来精准识别。
- 方法三:Number.isNaN()
-
Number.isNaN():它只判断传入的值是否严格等于NaN,不会进行类型转换。也就是说,只有当参数是真正的NaN值时,才会返回true。 -
全局
isNaN():在判断之前会先尝试将传入的参数转换为数字类型,然后再判断是否为NaN。这可能会导致一些意外的结果,例如:
isNaN('abc'); // true,因为'abc'被转换为NaN
Number.isNaN('abc'); // false
应用场景
总之,理解NaN的特性、产生方式以及如何准确辨别它,对编写健壮的 JavaScript 代码至关重要,希望这篇分享能帮大家更好地驾驭这个特殊的 “数字”。