181

这条线有什么区别:

var a = parseInt("1", 10); // a === 1

这条线

var a = +"1"; // a === 1

这个jsperf 测试表明,一元运算符在当前的 chrome 版本中要快得多,假设它是针对 node.js 的!?

如果我尝试转换不是数字的字符串都返回NaN

var b = parseInt("test" 10); // b === NaN
var b = +"test"; // b === NaN

那么我什么时候应该更喜欢使用parseInt一元加号(尤其是在 node.js 中)???

编辑:双波浪号运算符有什么区别~~

4

6 回答 6

337

终极数字转换表: 换算表

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',
    'undefined',
    '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 }

于 2013-06-14T10:46:34.823 回答
199

好吧,这里有一些我知道的区别:

  • 一个空字符串""计算为 a 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将按字符解析。这意味着十六进制和指数符号将失败,因为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.
    
于 2013-06-14T10:46:34.200 回答
11

我认为 thg435 的答案中的表格很全面,但是我们可以用以下模式进行总结:

  • 一元加号不会对所有假值都一视同仁,但它们都是假的。
  • 一元加号发送true到 1,但发送"true"NaN.
  • 另一方面,parseInt对于不是纯数字的字符串更为自由。 parseInt('123abc') === 123, 而+报告NaN.
  • Number将接受有效parseInt的十进制数字,而只会删除小数点后的所有内容。因此parseInt模仿了 C 的行为,但可能不适合评估用户输入。
  • 两者都修剪字符串中的空格。
  • parseInt,作为一个设计糟糕的解析器,接受八进制和十六进制输入。一元加号只需要十六进制。

Falsy 值转换为Number遵循 C: 中有意义的 值null,并且false都为零。 ""去 0 并不完全遵循这个约定,但对我来说足够有意义。

因此,我认为如果您正在验证用户输入,一元加号除了接受小数外,对所有内容都有正确的行为(但在我的现实生活中,我更感兴趣的是捕获电子邮件输入而不是 userId,值完全省略等),而parseInt 太自由了。

于 2013-06-27T17:39:42.643 回答
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

基准测试源代码:


/* 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()
    
}
于 2021-01-05T22:33:13.947 回答
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));
于 2015-03-11T18:43:06.070 回答
-3

还要考虑性能。我很惊讶parseInt在 iOS 上胜过一元加 :) 这仅对 CPU 消耗量大的 Web 应用程序很有帮助。作为一个经验法则,我建议 JS opt-guys 从当今移动性能的角度考虑任何 JS 运营商而不是另一个运营商。

所以,移动优先;)

于 2013-07-19T14:08:04.260 回答