在日常开发中,我们常常会遇到一些“看似合理却出人意料”的数值运算结果。比如:
js
编辑
console.log(8 / 0); // Infinity
console.log(0 / 0); // NaN
console.log(parseInt('八百108')); // NaN
console.log("abc" - 123); // NaN
console.log(undefined + 5); // NaN
这些输出背后,隐藏着 JavaScript 数值系统中的两个特殊值:NaN(Not-a-Number) 和 Infinity(无穷大) 。它们不是错误,而是语言规范中明确定义的行为。然而,若对其理解不深,极易引发逻辑 bug 或调试困境。
本文将系统解析 NaN 与 Infinity 的来源、特性、判断方法及使用注意事项,并结合真实代码场景,帮助你避开常见陷阱。
一、什么是 NaN?
1. 定义
NaN 表示“不是一个数字”(Not-a-Number),用于表示无效或未定义的数学运算结果。
2. 常见产生场景
| 表达式 | 结果 | 说明 |
|---|---|---|
0 / 0 | NaN | 无意义的除法 |
Math.sqrt(-1) | NaN | 负数开平方(实数范围内无解) |
"abc" - 123 | NaN | 字符串无法转为有效数字进行运算 |
parseInt("hello") | NaN | 无法解析数字 |
undefined + 5 | NaN | undefined 转数字为 NaN |
⚠️ 注意:
NaN的类型是number!
js
编辑
console.log(typeof NaN); // "number"
3. 最诡异的特性:NaN !== NaN
js
编辑
console.log(NaN === NaN); // false
console.log(NaN == NaN); // false
这是 IEEE 754 浮点数标准的规定:任何涉及 NaN 的比较都返回 false。
因此,不能用 == 或 === 判断是否为 NaN!
✅ 正确判断方式
js
编辑
// 方法1:Number.isNaN()(推荐)
Number.isNaN(NaN); // true
Number.isNaN("abc"); // false(不会隐式转换)
// 方法2:全局 isNaN()(慎用)
isNaN(NaN); // true
isNaN("abc"); // true ❌(先尝试转数字,"abc" → NaN)
📌 最佳实践:优先使用
Number.isNaN(),避免类型转换带来的误判。
二、什么是 Infinity?
1. 定义
Infinity 表示正无穷大,-Infinity 表示负无穷大,用于表示超出 JavaScript 数值范围的结果。
2. 常见产生场景
| 表达式 | 结果 |
|---|---|
6 / 0 | Infinity |
-6 / 0 | -Infinity |
Math.pow(10, 1000) | Infinity(超出最大安全整数) |
3. 特性
-
类型也是
number:js 编辑 console.log(typeof Infinity); // "number" -
可参与比较:
js 编辑 console.log(Infinity > 999999999999); // true console.log(-Infinity < -999999999999); // true -
Infinity === Infinity为true(与NaN不同)
✅ 判断是否为无穷大
js
编辑
console.log(isFinite(100)); // true
console.log(isFinite(Infinity)); // false
console.log(isFinite(NaN)); // false
三、NaN vs Infinity 对比总结
| 特性 | NaN | Infinity |
|---|---|---|
| 含义 | 非数字 | 无穷大 |
| 类型 | number | number |
| 比较自身 | NaN !== NaN | Infinity === Infinity |
| 产生原因 | 无效运算(如 0/0) | 超界运算(如 1/0) |
| 判断方法 | Number.isNaN(x) | !isFinite(x) && x !== NaN 或直接比较 |
| 是否可参与计算 | 否(传播性:任何含 NaN 的运算结果都是 NaN) | 是(如 Infinity + 1 === Infinity) |
四、常见误区与最佳实践
❌ 误区1:用 == 判断 NaN
js
编辑
if (a == NaN) { ... } // 永远为 false!
✅ 正确做法:
js
编辑
if (Number.isNaN(a)) { ... }
❌ 误区2:认为 parseInt('1314.520') 返回浮点数
js
编辑
console.log(parseInt('1314.520')); // 1314(只取整数部分)
parseInt遇到小数点即停止解析!
❌ 误区3:混淆 isNaN() 与 Number.isNaN()
js
编辑
isNaN("hello"); // true(因为 "hello" → NaN)
Number.isNaN("hello"); // false(严格判断,不转换类型)
五、大厂高频面试题
🔹 面试题 1:为什么 NaN !== NaN?如何正确判断一个值是 NaN?
考察点:对 IEEE 754 标准的理解、Number.isNaN 与 isNaN 的区别。
🔹 面试题 2:以下代码输出什么?为什么?
js
编辑
console.log(0 / 0);
console.log(1 / 0);
console.log(typeof (0 / 0));
console.log((0 / 0) === (0 / 0));
答案:
text
编辑
NaN
Infinity
"number"
false
🔹 面试题 3:实现一个函数,安全地判断一个值是否为“有效数字”(排除 NaN 和 Infinity)。
参考答案:
js
编辑
function isValidNumber(val) {
return typeof val === 'number' &&
!Number.isNaN(val) &&
isFinite(val);
}
🔹 面试题 4:parseInt('八百108') 和 parseInt('108八百') 分别返回什么?
答案:
'八百108'→NaN(开头非数字)'108八百'→108(从左开始解析,遇到非数字停止)
六、结语
NaN 和 Infinity 是 JavaScript 数值系统的“边界守卫者”。它们的存在让程序能在异常运算中保持运行而不崩溃,但也带来了独特的陷阱。理解它们的产生机制、行为特性和正确判断方式,是写出健壮前端代码的必备技能。
记住:
NaN是“毒药” :一旦出现,会污染整个计算链;Infinity是“极限” :代表数值的边界,但仍可比较和运算;- 永远不要用
==判断NaN; - 优先使用
Number.isNaN()和isFinite()。
掌握这些,你就能在数值处理的迷宫中从容前行。
标签推荐:
#JavaScript #前端 #NaN #Infinity #面试 #大厂面试题 #Web开发