先记住这个答案
区别只有一个:转不转类型。全局 isFinite(v) 会先执行 Number(v),再判断结果是不是有限数;Number.isFinite(v) 先检查 v 是不是 number 类型,不是就直接返回 false。所以 isFinite('42') 是 true,Number.isFinite('42') 是 false。实际项目里判断「这个值是不是一个有限的数字」,用 Number.isFinite。
isFinite先转数字再判断,会误放行Number.isFinite只认 number 类型- 全局
isFinite会先做类型转换 - 显式转换后用
Number.isFinite校验
同一组值,两种结果
最直观的办法是拿一堆不同类型的值分别喂给两个函数。
const cases = [42, '42', '', ' ', null, undefined, true, [], [7], {}, NaN, Infinity]
for (const v of cases) {
const label = typeof v === 'string' ? `'${v}'` : Array.isArray(v) ? `[${v}]` : String(v)
console.log(label.padEnd(10), isFinite(v), Number.isFinite(v))
}查看输出与解释
42 true true
'42' true false
'' true false
' ' true false
null true false
undefined false false
true true false
[] true false
[7] true false
[object Object] false false
NaN false false
Infinity false false只有第一行 42 两边都是 true。中间一大段全是 isFinite 放行、Number.isFinite 拒绝的情况,原因都能追到 Number() 的转换规则上:Number('') 和 Number(' ') 是 0,Number(null) 是 0,Number(true) 是 1,Number([]) 是 0,Number([7]) 是 7。undefined 和 {} 转出来是 NaN,所以两边都是 false。
表单校验里怎么用才对
最常见的场景是校验输入框里的金额、数量。输入框拿到的永远是字符串,这时两个函数都不能直接用。
- 用
isFinite会放过空输入 isFinite(input)看起来能用,因为'12.5'会返回true。问题是用户什么都没填、或者只敲了空格,Number('')是 0,也会返回true,空表单就被当成了金额 0 提交上去。- 用
Number.isFinite要先转换 - 直接
Number.isFinite(input)则永远是false,因为input是字符串。正确的写法是分两步:先排除空输入,再显式转换后判断。写成input.trim() !== '' && Number.isFinite(Number(input)),空串、纯空格、'abc'、'Infinity'都会被拦下。 这样写的好处是每一步做什么都看得见:转换规则由Number()负责,有限性由Number.isFinite负责,不会有藏在函数内部的隐式转换。如果业务允许'12px'这种带单位的写法,就把Number换成parseFloat,这是有意识的选择,而不是被isFinite悄悄放过。
容易答错的地方
- 以为区别只在数字字符串上
- 很多人只记得
'42'的例子。实际上null、空字符串、布尔值、空数组、只有一个元素的数组,全都会被全局isFinite当成有限数。这些值出现在校验逻辑里,往往意味着数据本身就有问题,却被放行了。 - 以为
Number.isFinite更「严格」,所以结果会更少true - 对 number 类型的参数,两者结果完全一致,
Number.isFinite并没有额外的规则。它只是跳过了类型转换,并不会对数字本身做更严格的检查,比如小数、负数、-0都返回true。
面试官还会怎么问?
isNaN 和 Number.isNaN 是不是同样的关系?
是的。全局 isNaN('abc') 返回 true,因为 Number('abc') 是 NaN;Number.isNaN('abc') 返回 false,因为 'abc' 不是 number 类型。ES2015 把这两个函数挂到 Number 上,就是为了提供不做隐式转换的版本。
传一个 BigInt 进去会怎样?
Number.isFinite(1n) 返回 false,因为 BigInt 不是 number 类型。全局 isFinite(1n) 会直接抛 TypeError,因为它内部做的数字转换不允许把 BigInt 隐式转成 Number。这个例子能看出全局版本的转换不只是「宽松」,还可能直接报错。
判断一个值是不是整数用什么?
用 Number.isInteger,它同样不做类型转换,Number.isInteger('5') 是 false。如果还要保证整数能被精确表示,比如 ID、计数,用 Number.isSafeInteger,它会把超过 2^53 - 1 的数排除掉。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。