parseInt vs unary plus - 何时使用哪个

时间:2013-06-14 10:44:56

标签: javascript node.js

这一行之间有什么区别:

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中)?

修改:和双波形符号运算符~~有什么区别?

6 个答案:

答案 0 :(得分:220)

最终的无数转换表: enter image description here

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)

有关更完整的案例

,请参阅this answer


嗯,这里有一些我所知道的差异:

  • 空字符串""评估为0,而parseInt评估结果为NaN。 IMO,空白字符串应为NaN

    +'' === 0;              //true
    isNaN(parseInt('',10)); //true
    
  • 一元+更像parseFloat,因为它也接受小数。

    另一方面,

    parseInt在看到非数字字符时会停止解析,例如小时点.

    +'2.3' === 2.3;           //true
    parseInt('2.3',10) === 2; //true
    
  • parseIntparseFloat解析并构建字符串从左到右。如果他们看到一个无效字符,它会将已解析的内容(如果有)作为数字返回,如果没有解析为数字,则返回NaN

    如果整个字符串不可转换为数字,则另一方面,一元+将返回NaN

    parseInt('2a',10) === 2; //true
    parseFloat('2a') === 2;  //true
    isNan(+'2a');            //true
    
  • @Alex K.的评论中所示,parseIntparseFloat将按字符进行解析。这意味着十六进制和指数表示法将失败,因为xe被视为非数字组件(至少在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值会转换为Numbernullfalse都为零。 ""转到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运营商而不是另一个。

所以,去移动优先;)

相关问题