NaN 永远不等于 NaN 是因 IEEE 754 标准规定,JavaScript 继承此行为;isNaN() 有类型转换陷阱,应优先使用 Number.isNaN() 或 Object.is() 检测。
因为这是 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)这种不可靠的类型转换让它不适合用于精确检测。
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() 也能识别 NaNObject.is() 是 ES6 引入的严格相等判断,它把 NaN 视为相同值(即 Object.is(NaN, NaN) === true),同时还能区分 +0 和 -0。
所以检测 NaN 的另一种写法是:
Object.is(value, NaN)
但它比 Number.isNaN() 多一次值比较开销,语义也不如后者直接;仅在你已用 Object.is() 做其他一致性判断时顺带使用更自然。
真正容易被忽略的是:很多人在写条件分支时仍习惯用 value !== value 来“黑科技”检测 NaN,虽然它确实有效(因为只有 NaN 满足该条件),但可读性差、意图不明确,维护时容易被误删或误解。