这一行之间有什么区别:
var a = parseInt("1", 10); // a === 1
和这一行
var a = +"1"; // a === 1
这个jsperf test表明一元运算符在当前的chrome版本中更快,假设它是针对node.js的!?
如果我尝试转换非数字的字符串,则返回NaN
:
var b = parseInt("test" 10); // b === NaN
var b = +"test"; // b === NaN
那么我什么时候应该优先使用parseInt
而不是一元加(特别是在node.js中)?
修改:和双波形符号运算符~~
有什么区别?
答案 0 :(得分:220)
EXPRS = [
'parseInt(x)',
'parseFloat(x)',
'Number(x)',
'+x',
'~~x',
'x>>>0',
'isNaN(x)'
];
VALUES = [
'"123"',
'"+123"',
'"-123"',
'"123.45"',
'"-123.45"',
'"12e5"',
'"12e-5"',
'"0123"',
'"0000123"',
'"0b111"',
'"0o10"',
'"0xBABE"',
'"4294967295"',
'"123456789012345678"',
'"12e999"',
'""',
'"123foo"',
'"123.45foo"',
'" 123 "',
'"foo"',
'"12e"',
'"0b567"',
'"0o999"',
'"0xFUZZ"',
'"+0"',
'"-0"',
'"Infinity"',
'"+Infinity"',
'"-Infinity"',
'null',
'[].undef',
'true',
'false',
'Infinity',
'NaN',
'{}',
'{valueOf: function(){return 42}}',
'{toString: function(){return "56"}}',
];
//////
function wrap(tag, s) {
if (s && s.join)
s = s.join('');
return '<' + tag + '>' + String(s) + '</' + tag + '>';
}
function table(head, rows) {
return wrap('table', [
wrap('thead', tr(head)),
wrap('tbody', rows.map(tr))
]);
}
function tr(row) {
return wrap('tr', row.map(function (s) {
return wrap('td', s)
}));
}
function val(n) {
return n === true || Number.isNaN(n) ? wrap('b', n) : String(n);
}
var rows = VALUES.map(function (v) {
var x = eval('(' + v + ')');
return [v].concat(EXPRS.map(function (e) {
return val(eval(e))
}));
});
document.body.innerHTML = table(["x"].concat(EXPRS), rows);
table { border-collapse: collapse }
tr:nth-child(odd) { background: #fafafa }
td { border: 1px solid #e0e0e0; padding: 5px; font: 12px monospace }
td:not(:first-child) { text-align: right }
thead td { background: #3663AE; color: white }
b { color: red }
答案 1 :(得分:142)
嗯,这里有一些我所知道的差异:
空字符串""
评估为0
,而parseInt
评估结果为NaN
。 IMO,空白字符串应为NaN
。
+'' === 0; //true
isNaN(parseInt('',10)); //true
一元+
更像parseFloat
,因为它也接受小数。
parseInt
在看到非数字字符时会停止解析,例如小时点.
。
+'2.3' === 2.3; //true
parseInt('2.3',10) === 2; //true
parseInt
和parseFloat
解析并构建字符串从左到右。如果他们看到一个无效字符,它会将已解析的内容(如果有)作为数字返回,如果没有解析为数字,则返回NaN
。
如果整个字符串不可转换为数字,则另一方面,一元+
将返回NaN
。
parseInt('2a',10) === 2; //true
parseFloat('2a') === 2; //true
isNan(+'2a'); //true
如@Alex K.的评论中所示,parseInt
和parseFloat
将按字符进行解析。这意味着十六进制和指数表示法将失败,因为x
和e
被视为非数字组件(至少在base10上)。
一元+
会正确转换它们。
parseInt('2e3',10) === 2; //true. This is supposed to be 2000
+'2e3' === 2000; //true. This one's correct.
parseInt("0xf", 10) === 0; //true. This is supposed to be 15
+'0xf' === 15; //true. This one's correct.
答案 2 :(得分:10)
我认为thg435的答案中的表格是全面的,但我们可以用以下模式进行总结:
true
发送至1,"true"
发送至NaN
。parseInt
对于非纯数字的字符串更为宽松。 parseInt('123abc') === 123
,而+
报告NaN
。Number
将接受有效的十进制数,而parseInt
仅删除小数后的所有内容。因此parseInt
模仿C行为,但可能不适合评估用户输入。parseInt
,是一个设计糟糕的解析器,接受八进制和十六进制输入。一元加只采取hexademical。根据C中有意义的内容,Falsy值会转换为Number
:null
和false
都为零。 ""
转到0并不完全遵循这个惯例,但对我来说足够了。
因此,我认为如果您正在验证用户输入,一元加上除了接受小数之外的所有内容都有正确的行为(但在我的实际情况中,我更感兴趣的是捕获电子邮件输入而不是userId,值完全省略等等。 ),而parseInt太自由了。
答案 3 :(得分:1)
我建议使用 Math.floor(或者 ~~ 如果你知道数字是正数)而不是 parseString。 +(expression) 超出范围,因为 +(expression) 更像 parseFloat。看看这个小基准:
// 1000000 iterations each one
node test_speed
Testing ~~, time: 5 ms
Testing parseInt with number, time: 25 ms
Testing parseInt with string, time: 386 ms
Testing Math.floor, time: 18 ms
benchmark 源码:
/* el propósito de este script es evaluar
que expresiones se ejecutan más rápido para así
decidir cuál usar */
main()
async function main(){
let time, x
let number = 23456.23457
let test1 = ()=>{
x = 0
time = Date.now()
for(let i=0;i<1000000;i++){
let op = Math.floor(number / 3600)
x = op
}
console.info("Testing Math.floor, time:", Date.now() - time, "ms")
}
let test2 = ()=>{
x = 0
time = Date.now()
for(let i=0;i<1000000;i++){
let op = parseInt(number / 3600)
x = op
}
console.info("Testing parseInt with number, time:", Date.now() - time, "ms")
}
let test3 = ()=>{
x = 0
time = Date.now()
for(let i=0;i<1000000;i++){
let op = parseInt((number / 3600).toString())
x = op
}
console.info("Testing parseInt with string, time:", Date.now() - time, "ms")
}
let test4 = ()=>{
x = 0
time = Date.now()
for(let i=0;i<1000000;i++){
let op = ~~(number / 3600)
x = op
}
console.info("Testing ~~, time:", Date.now() - time, "ms")
}
test4()
test2()
test3()
test1()
}
答案 4 :(得分:0)
小心,parseInt比Node.JS中的+一元运算符更快, 错误的是+或| 0更快,它们只对NaN元素更快。
检查出来:
var arg=process.argv[2];
rpt=20000;
mrc=1000;
a=[];
b=1024*1024*1024*1024;
for (var i=0;i<rpt;i++)
a[i]=Math.floor(Math.random()*b)+' ';
t0=Date.now();
if ((arg==1)||(arg===undefined))
for (var j=0;j<mrc;j++) for (var i=0;i<rpt;i++) {
c=a[i]-0;
}
t1=Date.now();
if ((arg==2)||(arg===undefined)) {
for (var j=0;j<mrc;j++) for (var i=0;i<rpt;i++) {
d=a[i]|0;
}
}
t2=Date.now();
if ((arg==3)||(arg===undefined)) {
for (var j=0;j<mrc;j++) for (var i=0;i<rpt;i++) {
e=parseInt(a[i]);
}
}
t3=Date.now();
if ((arg==3)||(arg===undefined)) {
for (var j=0;j<mrc;j++) for (var i=0;i<rpt;i++) {
f=+a[i];
}
}
t4=Date.now();
console.log(a[i-1],c,d,e,f);
console.log('Eseguiti: '+rpt*mrc+' cicli');
console.log('parseInt '+(t3-t2));
console.log('|0 '+(t2-t1));
console.log('-0 '+(t1-t0));
console.log('+ '+(t4-t3));
答案 5 :(得分:-3)
也考虑performance。我很惊讶parseInt
在iOS上击败了一元加上:)这对于仅占用大量CPU的网络应用程序很有帮助。根据经验,我建议JS opt-guys从移动性能的角度考虑任何JS运营商而不是另一个。
所以,去移动优先;)