nan 不等于它自己,这是 ieee 754 与 ecmascript 共同规定的明确设计,旨在将其作为“计算失效信号”;检测应使用 number.isnan() 或 object.is(),而非 === 或已过时的 isnan()。

NaN 在 JavaScript 中不等于它自己,这是最典型的反直觉行为。它不是 bug,而是 IEEE 754 标准与 ECMAScript 规范共同决定的明确设计——目的是让 NaN 成为一种可靠的“计算失效信号”,而不是一个可参与常规比较的数值。
为什么 NaN !== NaN?
根本原因在于 NaN 的语义:它代表“不是一个有效数字”,而非某个具体值。IEEE 754 标准规定,所有涉及 NaN 的比较(包括 ===、==、、<code>>)一律返回 false。ECMAScript 规范直接采纳了这一规则,并在严格相等算法中明确写出:“若 x 或 y 是 NaN,则返回 false”。
这背后有实际考量:
- 不同运算产生的 NaN 可能对应不同错误源(如
0/0和Math.sqrt(-1)),底层二进制表示也可能不同,无法定义“相等” - 如果允许
NaN === NaN为 true,就可能掩盖错误——比如一个 NaN 被误当作合法中间结果继续参与计算,最终污染整个数据流 - 强制返回 false,反而让开发者必须显式处理异常状态,提升健壮性
如何正确检测 NaN?
不能用 value === NaN 或 value == NaN,它们永远是 false。可靠方法只有两个:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
Number.isNaN(value):推荐首选。只对真正类型为number且值为 NaN 的情况返回true -
Object.is(value, NaN):ES6 引入,用于判断两个值是否“完全相同”。它把 NaN 视为自洽的单一值,因此Object.is(NaN, NaN)返回true
注意:isNaN(value) 已过时,它会先尝试把参数转成数字再判断,导致 isNaN("hello") 和 isNaN(undefined) 都返回 true,容易误判。
NaN 在数组和对象操作中的表现
它的“不自反”特性会直接影响常用 API 的行为:
-
[NaN].indexOf(NaN)返回-1(因为indexOf内部用===比较) -
[NaN].includes(NaN)返回true(ES2016 起,includes使用Object.is语义) -
new Set([NaN, NaN]).size是1(Set 去重使用Object.is) - Lodash 的
_.isEqual(NaN, NaN)返回true,但_.isEqual(+0, -0)也返回true(它统一按“值等价”处理,不区分正负零)
NaN 的类型和常见来源
尽管叫 “Not a Number”,typeof NaN 却是 "number"。这是历史兼容性与 IEEE 754 实现方式决定的——NaN 是浮点数格式中的一种特殊编码,属于 Number 类型的合法成员。
典型产生场景包括:
- 数学无效运算:
0 / 0、Math.sqrt(-1)、Math.log(-1) - 强制类型转换失败:
Number("abc")、parseInt("hello") - 运算中混入无效值:
NaN + 5、10 * NaN结果仍是NaN
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










