NaN 永远不等于 NaN 是因 IEEE 754 标准规定,JavaScript 继承此行为;isNaN() 有类型转换陷阱,应优先使用 Number.isNaN() 或 Object.is() 检测。

NaN 为什么永远不等于 NaN?
因为这是 IEEE 754 浮点数标准的明确规定:NaN !== NaN 恒为 true。JavaScript 继承了这一行为——NaN 表示“不是一个有效数字”,它本身没有确定的数值意义,所以无法参与任何相等性比较(包括 ==、===、Object.is() 以外的所有常规比较)。
这意味着以下全部返回 false:
NaN == NaN NaN === NaN NaN === Number.NaN Object.is(NaN, NaN) // ✅ 这个是 true,但属于特例
用 isNaN() 要小心类型转换陷阱
isNaN() 会先尝试把参数转成数字,再判断是否为 NaN。这导致很多非数字值(比如空字符串、null、布尔值)被隐式转换后变成 0 或 1,从而返回 false,造成误判。
-
isNaN(" ")→false(空格转成0) -
isNaN(null)→false(null转成0) -
isNaN({})→true({}转成"[object Object]",再转数字得NaN)
这种不可靠的类型转换让它不适合用于精确检测。
立即学习“Java免费学习笔记(深入)”;
推荐用 Number.isNaN() 做严格判断
Number.isNaN() 不做任何类型转换,只当参数**本来就是数字类型且值为 NaN** 时才返回 true。这是目前最安全、语义最清晰的检测方式。
-
Number.isNaN(NaN)→true -
Number.isNaN(0 / 0)→true -
Number.isNaN("NaN")→false(字符串,不是数字类型) -
Number.isNaN(undefined)→false -
Number.isNaN({})→false
如果你需要兼容老环境(IE),可用 polyfill:
if (!Number.isNaN) {
Number.isNaN = function(value) {
return typeof value === 'number' && isNaN(value);
};
}特殊情况:Object.is() 也能识别 NaN
Object.is() 是 ES6 引入的严格相等判断,它把 NaN 视为相同值(即 Object.is(NaN, NaN) === true),同时还能区分 +0 和 -0。
所以检测 NaN 的另一种写法是:
Object.is(value, NaN)
但它比 Number.isNaN() 多一次值比较开销,语义也不如后者直接;仅在你已用 Object.is() 做其他一致性判断时顺带使用更自然。
真正容易被忽略的是:很多人在写条件分支时仍习惯用 value !== value 来“黑科技”检测 NaN,虽然它确实有效(因为只有 NaN 满足该条件),但可读性差、意图不明确,维护时容易被误删或误解。











