写 JavaScript 的时候,我们经常会遇到要判断一个值是不是“有限的数”或者是不是“不是一个数(NaN)”。早期的 ES5 提供了两个全局函数:isFinite() 和 isNaN();后来到了 ES6,又在 Number 对象上加了两个新方法:Number.isFinite() 和 Number.isNaN()。看起来它们干的是差不多的事,但其实用起来差别挺大。这篇文章就用简单的话和例子,把它们的不同讲明白,帮你少踩坑。
一、isFinite() 和 Number.isFinite() 有什么不同
1. 全局的 isFinite() 是怎么工作的
- 它是干啥的:用来检查你给它的值,最后能不能变成一个正常的、不是无穷大的数字。
- 它会偷偷做一件事:先把你的值用
Number()转一下,不管原来是什么类型,都先试着变成数字,然后再看这个数字是不是有限的。
比如:
console.log(isFinite(123)); // true,本来就是数字
console.log(isFinite('123')); // true,字符串 '123' 被转成了数字 123
console.log(isFinite('abc')); // false,'abc' 转出来是 NaN
console.log(isFinite(true)); // true,true 被当成 1
console.log(isFinite(null)); // true,null 被当成 0
2. Number.isFinite() 更老实
- 它是干啥的:只看你传进来的东西是不是一个真正的数字,并且这个数字不能是无穷大或者 NaN。
- 它不会乱动你的数据:如果你传的是字符串、布尔值或者其他类型,它直接说“不行”,根本不去尝试转换。
比如:
console.log(Number.isFinite(123)); // true,是数字,也没问题
console.log(Number.isFinite('123')); // false,虽然是数字样子的字符串,但它不是数字类型
console.log(Number.isFinite(NaN)); // false
console.log(Number.isFinite(Infinity)); // false
console.log(Number.isFinite(true)); // false,布尔值不算数字
✅ 简单说:
Number.isFinite()更靠谱,因为它不乱改你的数据,只认真正的数字。
二、isNaN() 和 Number.isNaN() 差在哪
1. 全局的 isNaN() 容易让人误会
- 它表面上是查 NaN,实际上不是:它先把你给的值转成数字,如果转完是 NaN,就返回 true。所以它其实是在问:“这东西能变成正常数字吗?”而不是“它是不是 NaN?”
举个例子:
console.log(isNaN(NaN)); // true,确实是 NaN
console.log(isNaN('abc')); // true,因为 'abc' 转数字失败,变成 NaN
console.log(isNaN('123')); // false,'123' 能转成 123,没问题
console.log(isNaN(undefined)); // true,undefined 转数字是 NaN
console.log(isNaN({})); // true,对象转数字也是 NaN
console.log(isNaN(true)); // false,true 转成 1,不是 NaN
⚠️ 问题来了:isNaN("hello") 返回 true,但 "hello" 根本不是 NaN,它只是一个字符串!这种设计很容易让人搞错逻辑。
2. Number.isNaN() 才是真的查 NaN
- 它只做一件事:看看你给的值是不是严格等于
NaN。 - 它很死板:如果不是数字类型,直接返回 false;只有当值本身就是
NaN时,才返回 true。
比如:
console.log(Number.isNaN(NaN)); // true,真的是 NaN
console.log(Number.isNaN('NaN')); // false,这是字符串,不是 NaN
console.log(Number.isNaN(undefined)); // false,不是数字
console.log(Number.isNaN(123)); // false,是正常数字
console.log(Number.isNaN('abc')); // false,字符串再像 NaN 也没用
✅ 记住这一点:
Number.isNaN()只对真正的NaN说“是”,其他所有情况都说“不是”。
三、为啥推荐用 Number 上的那两个方法?
| 方法 | 会不会自动转类型 | 判断严不严 | 容不容易出错 |
|---|---|---|---|
isFinite() |
会 | 不严 | ❌ 容易误判 |
Number.isFinite() |
不会 | 严 | ✅ 更安全 |
isNaN() |
会 | 不严 | ❌ 容易误解 |
Number.isNaN() |
不会 | 严 | ✅ 更准确 |
在实际写代码的时候(比如验证用户输入、处理后台返回的数据、清洗原始信息等),用 Number.isNaN() 能避免把像 "error" 这样的字符串当成 NaN 来处理,这样程序就不容易出错,也更好理解。
四、怎么用才好?老浏览器怎么办?
- 最好的做法:平时就用
Number.isNaN()和Number.isFinite(),别用全局的那两个。 - 如果要支持老浏览器(比如 IE):可以自己加一段代码来补上:
if (!Number.isNaN) {Number.isNaN = function(value) {return typeof value === 'number' && isNaN(value);};
}
- 如果你用 TypeScript:
Number.isNaN还有个好处,它能让编辑器知道某个变量现在肯定是NaN,帮你减少类型错误。
最后说两句
JavaScript 很灵活,但也正因为太灵活,有些老方法(比如 isNaN 和 isFinite)会悄悄转换类型,结果让人意想不到。ES6 加的 Number.isNaN 和 Number.isFinite 就是为了修这个问题——它们不乱转类型,行为更清楚,用起来更放心。作为现在的前端开发者,我们应该多用这些新方法,写出更简单、更不容易出错的代码。
📌 一句话记牢:
只有原原本本的NaN,才能让Number.isNaN()返回 true,别的都不行!
