isNaN()
和 Number.isNaN()
都是 JavaScript 中用于检查一个值是否为 NaN
(Not-a-Number)的函数,但它们的行为有本质区别,尤其是在处理非数字类型的输入时。
一、isNaN()
(全局函数)
行为:
- 会先尝试将传入的值转换为数字,然后再判断转换后的结果是否为
NaN
。 - 这意味着它不仅检查“是否是
NaN
”,还会检查“是否能转换为有效数字”。
示例:
isNaN(NaN) // true ← 正常情况
isNaN("hello") // true ← "hello" 转为数字是 NaN
isNaN(undefined) // true ← undefined 转为数字是 NaN
isNaN({}) // true ← {} 转为数字是 NaN
isNaN("123") // false ← "123" 转为 123,是有效数字
isNaN(true) // false ← true 转为 1,是有效数字
问题:
- 它会将任何无法转换为有效数字的值都判定为
true
,而不仅仅是NaN
。 - 这可能导致误判,因为它混淆了“值本身就是
NaN
”和“值无法转换为数字”两种情况。
二、Number.isNaN()
(ES6 引入)
行为:
- 不会进行类型转换。
- 只有当传入的值本身就是
NaN
时,才返回true
。 - 如果传入的值不是
NaN
(即使它无法转换为数字),也返回false
。
示例:
Number.isNaN(NaN) // true ← 值本身就是 NaN
Number.isNaN("hello") // false ← "hello" 不是 NaN,只是无法转换
Number.isNaN(undefined) // false ← undefined 不是 NaN
Number.isNaN({}) // false ← {} 不是 NaN
Number.isNaN("123") // false ← "123" 不是 NaN
Number.isNaN(123) // false ← 123 不是 NaN
三、关键区别对比
输入值 | isNaN() | Number.isNaN() | 说明 |
---|---|---|---|
NaN | true | true | 两者一致 |
"hello" | true | false | isNaN 转换后为 NaN ;Number.isNaN 不转换 |
undefined | true | false | 同上 |
{} | true | false | 同上 |
"123" | false | false | 两者一致 |
123 | false | false | 两者一致 |
true | false | false | 两者一致 |
四、为什么 isNaN()
有“缺陷”?
isNaN()
是在早期 JavaScript 中定义的,它的设计初衷是检查“某个值是否代表一个无效的数字”,但由于它会强制转换类型,导致它实际上检查的是“某个值是否无法转换为有效数字”。
这在某些场景下可能有用,但通常我们只想知道一个值是否真的是 NaN
。
五、如何选择?
场景 | 推荐函数 | 原因 |
---|---|---|
检查一个值是否真的是 NaN | Number.isNaN() | 更精确,不进行类型转换,语义清晰 |
检查一个值是否能转换为有效数字 | isNaN() 或 Number.isNaN(Number(value)) | isNaN() 会自动转换,但语义模糊;更推荐显式转换后检查 |
现代开发 | 优先使用 Number.isNaN() | 它是 ES6 标准,行为更可靠 |
推荐的现代做法:
// 检查是否为 NaN
if (Number.isNaN(value)) {
console.log("value is NaN");
}
// 检查是否能转换为有效数字
if (Number.isNaN(Number(str))) {
console.log("str cannot be converted to a valid number");
}
六、Polyfill(兼容旧环境)
在不支持 Number.isNaN()
的旧环境中,可以这样模拟:
Number.isNaN = Number.isNaN || function(value) {
return typeof value === "number" && isNaN(value);
};
或者更精确地(因为 NaN !== NaN
):
Number.isNaN = Number.isNaN || function(value) {
return value !== value; // 只有 NaN 不等于自身
};
总结
函数 | 行为 | 推荐使用场景 |
---|---|---|
isNaN() | 先转换类型,再判断。任何无法转为有效数字的值都返回 true 。 | 避免使用,语义不清晰 |
Number.isNaN() | 不转换类型。只有当值本身就是 NaN 时才返回 true 。 | ✅ 推荐,精确、可靠 |
核心区别:isNaN()
会进行类型转换,而 Number.isNaN()
不会。在现代 JavaScript 开发中,应优先使用 Number.isNaN()
。
THE END