你不知道的javascript小知识之深入理解 JavaScript 中的 `NaN` 与 `Infinity`:陷阱、原理与最佳实践

122 阅读4分钟

在日常开发中,我们常常会遇到一些“看似合理却出人意料”的数值运算结果。比如:

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 或调试困境。

本文将系统解析 NaNInfinity 的来源、特性、判断方法及使用注意事项,并结合真实代码场景,帮助你避开常见陷阱。


一、什么是 NaN

1. 定义

NaN 表示“不是一个数字”(Not-a-Number),用于表示无效或未定义的数学运算结果

2. 常见产生场景

表达式结果说明
0 / 0NaN无意义的除法
Math.sqrt(-1)NaN负数开平方(实数范围内无解)
"abc" - 123NaN字符串无法转为有效数字进行运算
parseInt("hello")NaN无法解析数字
undefined + 5NaNundefined 转数字为 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 / 0Infinity
-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 对比总结

特性NaNInfinity
含义非数字无穷大
类型numbernumber
比较自身NaN !== NaNInfinity === 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.isNaNisNaN 的区别。

🔹 面试题 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(从左开始解析,遇到非数字停止)

六、结语

NaNInfinity 是 JavaScript 数值系统的“边界守卫者”。它们的存在让程序能在异常运算中保持运行而不崩溃,但也带来了独特的陷阱。理解它们的产生机制、行为特性和正确判断方式,是写出健壮前端代码的必备技能。

记住:

  • NaN 是“毒药” :一旦出现,会污染整个计算链;
  • Infinity 是“极限” :代表数值的边界,但仍可比较和运算;
  • 永远不要用 == 判断 NaN
  • 优先使用 Number.isNaN() 和 isFinite()

掌握这些,你就能在数值处理的迷宫中从容前行。


标签推荐
#JavaScript #前端 #NaN #Infinity #面试 #大厂面试题 #Web开发