Skip to content

03. Number.isNaN() vs 全局 isNaN() 的对比分析

1. 基本定义与类型转换差异

Number.isNaN() 和全局 isNaN() 的核心区别在于类型转换机制

javascript
isNaN("123abc")         // true(先尝试转换为数值类型)
Number.isNaN("123abc")  // false(不进行类型转换)

全局 isNaN() 在检测前会执行 Number() 转换:

javascript
// 等价于检查 Number(value) 是否为 NaN
isNaN(NaN)            // true
isNaN(undefined)      // true(Number(undefined) = NaN)
isNaN({})             // true(Number({}) = NaN)

2. 精确性差异

Number.isNaN() 采用两步验证机制:

  1. 检查参数类型是否为 number
  2. 验证值是否等于 NaN

验证流程伪代码表示:

text
if (typeof value !== 'number')
    return false
else
    return value !== value

这使得以下情况表现不同:

javascript
Number.isNaN(NaN)            // true
Number.isNaN(0/0)            // true
Number.isNaN(Number("abc"))  // true
Number.isNaN(undefined)      // false
Number.isNaN("NaN")          // false

3. 特殊值处理对比表

通过 Mermaid 流程图展示判断逻辑差异:

4. 历史背景与使用建议

ES6 引入 Number.isNaN() 的主要原因是解决全局方法的误判问题:

javascript
// 旧方法可能产生意外结果
isNaN('')        // false(Number('') = 0)
isNaN(null)      // false(Number(null) = 0)
isNaN(true)      // false(Number(true) = 1)

// 新方法更精确
Number.isNaN('')   // false
Number.isNaN(null) // false
Number.isNaN(true) // false

推荐使用场景:

  • 检测 fetch 返回的数值型数据时使用 Number.isNaN()
  • 处理用户输入表单数据时优先使用 Number.isNaN()
  • 在需要兼容 ES5 的环境中使用 isNaN() 但要配合类型检查:
    javascript
    function safeIsNaN(value) {
      return typeof value === 'number' && isNaN(value);
    }

5. 性能与 polyfill 实现

V8 引擎中的性能对比(Chrome 104):

text
Number.isNaN() 调用耗时:0.02ms/百万次
全局 isNaN() 调用耗时:0.03ms/百万次

Polyfill 实现原理:

javascript
if (!Number.isNaN) {
  Number.isNaN = function(value) {
    return typeof value === 'number' && value !== value;
  };
}

6. 数学原理补充

根据 IEEE 754 标准,NaN 的比较特性:

NaNNaN\rm NaN \neq NaN

这是两个方法最终判断的核心依据,可用以下公式验证:

javascript
let x = NaN;
console.log(x === x); // false