本文汇总了JavaScript中判断数值类型的多种方法,包括typeof、parseInt、isNaN及正则表达式。重点解析了全局方法与Number静态方法的区别,并推荐了结合parseFloat与isFinite的终极方案,该方案能准确处理字符串、null及布尔值,避免类型转换陷阱。
前言
在JavaScript中,判断一个值是否为数字有多种实现方式。
- 涉及typeof、instanceof、Number.isInteger等类型检查方法。
- 涉及parseInt、parseFloat等字符串解析方法。
- 涉及isNaN、isFinite等全局数值判断函数。
- 涉及Number.isNaN、Number.isFinite等ES6新增的严格判断方法。
- 涉及正则表达式匹配方案。
- 总结一种严谨的终极解决方案。
下文将逐一介绍上述方法,供读者参考。
1. typeof、instanceof、Number.isInteger
typeof用于判断值是否属于基本类型number,例如:
let num = 1;
typeof num === 'number'; // true
instanceof用于判断值是否属于包装类Number,例如:
let num = new Number(1);
num instanceof Number; // true
Number.isInteger用于判断值是否为整数,例如:
Number.isInteger(1); // true
Number.isInteger('1'); // false
Number.isInteger(1.1); // false
上述方法的共同缺陷在于仅基于类型进行判断,无法识别字符串形式的数值。
2. parseInt、parseFloat
该方法的核心特征是返回字符串开头最长的有效数字序列。
可以通过!isNaN(parseFloat(value))来尝试判断字符串是否为数值。
let str1 = '123';
let str2 = 'abc';
!isNaN(parseFloat(str1)); // true,是数字
!isNaN(parseFloat(str2)); // false,不是数字
parseInt和parseFloat在解析时遇到非法字符即停止,并返回已解析的数值。这意味着只要字符串头部包含合法数值,即便整体并非纯数值(如123abc),也能成功解析出数值部分。
因此,上述判断方式尚不够严谨,下文将介绍更为严谨的终极方案。
3. isNaN、isFinite
在介绍这两个函数前,需先了解NaN(Not-a-Number)。两个NaN值无法直接通过相等运算符比较,因为仅知其为非数值,具体状态不确定。
NaN === NaN; // false
NaN == NaN; // false
Object.is(NaN, NaN); // false
- isNaN(value)函数会将传入值通过ToNumber转换为数值,若结果为NaN则返回true,否则返回false。
- isFinite(value)函数会将传入值通过ToNumber转换为数值,若结果为有限数值(不等于Infinity或-Infinity)则返回true,否则返回false。
isNaN和isFinite均会先对传入值执行强制类型转换,其转换规则与直接使用Number函数一致。部分非数值在转换后可变为数值,例如:
Number(true); // 1
Number(false); // 0
Number(null); // 0
Number(''); // 0
对null、true、false、''调用isNaN返回false,但这些值本身并非数值,因此单独使用isNaN无法准确判断。
4. Number.isNaN、Number.isFinite
这两个方法与对应的全局函数存在显著差异。
- Number.isNaN(value)仅在value本身为NaN时返回true,否则返回false。
- Number.isFinite(value)仅在value本身为有限数值(不等于Infinity或-Infinity)时返回true,否则返回false。
主要区别在于全局方法会执行强制类型转换,而Number静态方法不会进行类型转换:
Number.isNaN(null); // true
Number.isNaN(true); // true
Number.isNaN(false); // true
Number.isNaN(''); // true
由于不进行类型转换,Number.isNaN判断null、true、false、''时结果均为true。
但其副作用是,数字字符串也会被判定为true:
Number.isNaN('123'); // true
Number.isNaN等价于以下实现:
Number.isNaN = Number.isNaN || function(value) {
return typeof value === "number" && isNaN(value);
}
Number.isFinite等价于以下实现:
if (Number.isFinite === undefined) Number.isFinite = function(value) {
return typeof value === 'number' && isFinite(value);
}
因此,这两个方法本质上仍基于类型判断,无法直接判断字符串是否为数值。
5. 正则表达式
let exp = /^[+-]?\d*(\.\d*)?(e[+-]?\d+)?$/;
exp.test('+1.9'); // true
exp.test('-.1e11'); // true
该正则表达式可匹配整数、浮点数、正负数及科学计数法格式。
不过,使用正则表达式判断数值略显繁琐,并非最优解。
6. 终极方案(推荐)
先展示该方案代码:
!isNaN(parseFloat(value)) && isFinite(value);
此代码源自jQuery中的$.isNumeric,简洁且优雅。
接下来分析其原理,以字符串123abc为例,预期结果应为false。
- parseFloat('123abc')返回123;
- !isNaN(123)返回true;
- isFinite('123abc')返回false;
- 最终组合结果为false。
单独使用!isNaN(parseFloat(value))会将123abc误判为数值,因此引入isFinite进行二次判断,isFinite的另一作用是排除无穷大数值。
!isNaN(parseFloat(Infinity)); // true
!isNaN(parseFloat(Infinity)) && isFinite(Infinity); // false
此外,由于parseFloat执行的是纯字符串解析而非类型转换,因此不会将null、true、false、''误判为数值。
!isNaN(parseFloat(null)) && isFinite(null); // false
!isNaN(parseFloat(true)) && isFinite(true); // false
!isNaN(parseFloat(false)) && isFinite(false); // false
!isNaN(parseFloat('')) && isFinite(''); // false
该方案设计巧妙,值得推荐。
7. 结语
本文对各类方法的介绍侧重于“判断值是否为数值”这一主题。这些方法中的任何一个单独展开均可撰写独立文章,后续如有机会将另行分享。
至此,关于JavaScript判断数字的几种方式介绍完毕。如需了解更多js判断数字相关内容,请搜索本站历史文章或继续浏览后续文章,感谢支持。