在JavaScript里,NaN算是最让人困惑的值之一。它的全称是Not a Number,表示一个“不是数字”的数字类型值。它的诡异之处在于:NaN === NaN返回的是false,也就是说NaN不等于它自己。这个特性直接导致了判断NaN不能用常规的相等比较,必须借助专门的手段。本文将从NaN的特性出发,详细介绍几种判断方式及其适用场景。

NaN是怎么产生的,为什么它不等于自己
在讲解判断方法之前,先弄清楚NaN的来源很有必要。NaN通常在以下几种情况下出现:把一个无法解析成数字的字符串传给Number()或parseFloat(),例如Number("abc")得到NaN;对NaN进行算术运算,结果依然是NaN;还有Math.sqrt(-1)这类对负数开平方的数学运算,也会返回NaN。此外,0/0的结果是NaN,但1/0返回的是Infinity,这一点经常被搞混。
至于为什么NaN不等于自己,这要追溯到IEEE 754浮点数标准。JavaScript的数字类型就是基于这个标准实现的。在IEEE 754中,NaN被定义为一种特殊的浮点数值,它的阶码位全为1,尾数位不全为0。标准明确规定,NaN与任何值(包括另一个NaN)进行比较时,无论使用等于、大于还是小于,结果都是false。这么设计的原因是,NaN的尾数位可以有多种取值,理论上存在很多个不同的NaN,它们可能携带不同的错误信息,无法确定彼此是否相等,干脆统一规定不相等。
理解了这个底层机制,你就明白为什么x === NaN这种写法永远返回false,即使x本身就是NaN。所以判断NaN必须绕开相等运算符,使用专门的方法。
全局函数isNaN的问题与Number.isNaN的正确用法
很多初学者第一反应是用全局的isNaN()函数,这个函数确实能判断NaN,但它的行为隐藏着一个大坑:isNaN()会先把参数转换成数字类型,然后再判断转换结果是不是NaN。这意味着只要一个值无法被安全地转换成数字,isNaN()就会返回true,哪怕这个值根本不是NaN。
看下面这个例子就一目了然了:
isNaN(NaN); // true,正确
isNaN("hello"); // true,错误!"hello"不是NaN,只是无法转成数字
isNaN(undefined); // true,同样错误
isNaN({}); // true,同样错误
isNaN("123"); // false,"123"能转成数字123
可以看到,isNaN("hello")返回true是因为字符串"hello"被隐式转换成了NaN,但"hello"本身并不是NaN类型的值。这在做数据校验时会产生误判。而ES6引入的Number.isNaN()则修复了这个问题,它不会对参数做任何类型转换,只有当参数真正是NaN类型时才返回true:
Number.isNaN(NaN); // true
Number.isNaN("hello"); // false,字符串不是NaN
Number.isNaN(undefined); // false
Number.isNaN(Number("hello")); // true,显式转换后才判断
所以结论很明确:在ES6及以上环境中,判断一个值是否为NaN,首选Number.isNaN()。如果需要兼容老旧的ES5环境,可以用x !== x这个技巧,利用NaN不等自身的特性,只有NaN会让这个表达式返回true。
Object.is与其他判断方式的对比
除了上面两种方法,ES6还提供了Object.is(),它可以用来比较两个值是否“相同”,采用了同值相等的算法。对于NaN,Object.is(NaN, NaN)返回true,这是它和严格相等运算符===的主要区别之一。不过在比较0和-0时,两者行为也不同:Object.is(0, -0)返回false,而0 === -0返回true。
Object.is(NaN, NaN); // true Object.is(0, -0); // false NaN === NaN; // false 0 === -0; // true
为了方便对比,把常见的判断方式整理成表格:
| 判断方式 | 是否类型转换 | isNaN("abc")结果 | 推荐场景 |
|---|---|---|---|
| isNaN() | 是 | true(误判) | 不推荐 |
| Number.isNaN() | 否 | false(正确) | 首选方案 |
| Object.is(x, NaN) | 否 | false(正确) | 可用,稍显冗长 |
| x !== x | 否 | false(正确) | ES5兼容场景 |
还有一个实际开发中容易遇到的场景:从接口拿到的数据是字符串形式的数字,比如“42”或者空字符串,需要先转换再判断。这时候要注意Number("")返回0而不是NaN,Number(null)也返回0,而Number(undefined)返回NaN。做数值校验时,合理的写法是先显式转换,再用Number.isNaN()检查:
function toNumber(value) {
const num = Number(value);
if (Number.isNaN(num)) {
return 0; // 或者其他默认值
}
return num;
}
toNumber("3.14"); // 3.14
toNumber("abc"); // 0
toNumber(""); // 0,注意空串转数字是0
总结一下,判断NaN的核心原则是:永远不要用==或===直接比较NaN,优先使用Number.isNaN(),避免使用会做隐式转换的全局isNaN()。理解NaN的IEEE 754底层机制,能帮助你在处理浮点数运算和数据清洗时更加得心应手。
JavaScriptNaN判断Number.isNaN修改时间:2026-09-07 14:08:33