我经常会看到其他程序员的代码中出现包含数字的变量,可能来自表单,又或者来自API调用的结果,不管什么原因,然后你想将它转换为整数。
例如:
const myNumber = '1';
if (parseInt(myNumber, 10) === 1) {
// do something
}
虽然上面的代码可以工作,但这是一种非常低效的解析方法。
你应该使用Number()函数,并将上面的代码转换为:
const myNumber = '1';
if (Number(myNumber) === 1) {
// do something
}
经过这样一改,有两个好处:
- 代码更易读
- 将字符串转换为整数的方法更高效
那么,Number()
和parseInt
有什么区别呢?
Number(string)
函数评估整个字符串并将其转换为数字,如果这个字符串不是一个数字,就返回NaN。
而parseInt(string, [radix])
会尝试在传递的字符串中找到第一个数字,将其转换为传递的基数,默认为10,只有在找不到任何数字时才会返回NaN。
这意味着如果你传递一个像5e2这样的字符串,那么,parseInt会在看到e时停止,因此只返回5,而Number则评估整个字符串并返回正确的值500。
你可以发现这两个函数之间有一些不同:
console.log(Number('a')); // NaN
console.log(Number('1')); // 1
console.log(Number('5e2')); // 500
console.log(Number('16px')); // NaN
console.log(Number('3.2')); // 3.2
console.log(parseInt('a')); // NaN
console.log(parseInt('1')); // 1
console.log(parseInt('5e2')); // 5
console.log(parseInt('16px')); // 16
console.log(parseInt('3.2')); // 3
这也是执行时间的问题
可能你还是有疑问,“我只是把一个简单的数字转换为整数,为什么要换用Number呢”?
原因在于性能。
例如,假设有这样一个简单的函数,循环一亿次,并接受回调,现在让我们调用这个函数两次,第一次使用Number,第二种使用parseInt。
function runBench(cb) {
const start = new Date();
for (let i = 0; i < 100000000; i++) {
cb();
}
const end = new Date();
console.log(`It took ${end - start} ms`);
}
const process1 = () => Number('3.2');
const process2 = () => parseInt('3.2', 10);
runBench(process1); // It took 140 ms
runBench(process2); // It took 4546 ms
实际情况下当然不可能运行1亿次循环,这里是为了让两个函数之间的性能差异变得明显。还有一点是,当你在同一个函数的多个地方使用parseInt时,最后结果可能就直接计算总和了。
那么我们应该一直避免使用parseInt吗?
不,并非总是如此,在某些用例中使用parseInt是有益的,比如你想从浮点数中推断出一个整数,那么parseInt比Math.round()快50%。
还有,如果你想将一个带有像素的字符串转换为数字,比如32px转换为32,那么你应该使用parseInt,但大多数时候你最好还是使用Number。
或者甚至如果你想将数字从十进制系统转换为其他进制的数字,也是如此。
总结
除非在某些特定情况下,parseInt能返回你所需要的东西而Number不能,那才选择parseInt。在99%的用例中,你最好还是选择Number。
更新:更多基准测试
因为还有其他方法可以将字符串转换为数字,下面我将使用parseFloat和一元运算符添加测试,请看结果:
function runBench(cb) {
const start = new Date();
for (let i = 0; i < 100000000; i++) {
cb();
}
const end = new Date();
console.log(`It took ${end - start} ms`);
}
const process1 = () => Number('1');
const process2 = () => parseInt('1', 10);
const process3 = () => parseFloat('1');
const process4 = () => +'1';
runBench(process1); // It took 70 ms
runBench(process2); // It took 4552 ms
runBench(process3); // It took 5082 ms
runBench(process4); // It took 412 ms
正如你在上面看到的,使用Number()仍然是最快的转换方法。