NodeJS parseInt与unary plus,何时使用哪个?

p5cysglq  于 2022-12-29  发布在  Node.js
关注(0)|答案(6)|浏览(107)

这条线有什么区别:

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

edit:和双波浪号操作符~~有什么区别?

gajydyqb

gajydyqb1#

我建议使用Math.floor(或者~~,如果你知道数字是正数的话)代替parseString。+(表达式)超出了范围,因为+(表达式)更像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()
    
}
azpvetkf

azpvetkf2#

也考虑一下performance。我很惊讶parseInt在iOS上击败了unary plus:)这只对CPU消耗很大的Web应用程序有帮助。作为一个经验法则,我建议JS opt-guys从移动的性能的Angular 考虑任何JS运营商而不是另一个。
所以,移动优先;)

cclgggtu

cclgggtu3#

最终的任意到数字转换表:

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"',
    'BigInt(1)',

    '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) || n === "Error" ? wrap('b', n) : String(n);
}

var rows = VALUES.map(function (v) {
    var x = eval('(' + v + ')');
    return [v].concat(EXPRS.map(function (e) {
        try {
            return val(eval(e));
        } catch {
            return val("Error");
        }
    }));
});

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 }
yeotifhr

yeotifhr4#

好吧,这里有几个我知道的区别:

  • 空字符串""的计算结果为0,而parseInt的计算结果为NaN。因此,空字符串应该为NaN
+'' === 0;              //true
  isNaN(parseInt('',10)); //true
  • 一元的+更像parseFloat,因为它也接受小数。

另一方面,parseInt在看到非数字字符时停止解析,例如预期作为小数点的句点.

+'2.3' === 2.3;           //true
  parseInt('2.3',10) === 2; //true
  • parseIntparseFloat解析并构建字符串 left to right。如果发现无效字符,则返回解析为数字的内容(如果有),如果没有解析为数字的内容,则返回NaN

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

parseInt('2a',10) === 2; //true
  parseFloat('2a') === 2;  //true
  isNaN(+'2a');            //true
  • 如@Alex K.的注解所示,parseIntparseFloat将按字符解析,这意味着十六进制和指数表示法将失败,因为xe被视为非数字部分(至少在以10为底的情况下)。

一元的+可以正确地转换它们。

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.
ccrfmcuu

ccrfmcuu5#

我相信thg435的回答中的表格是全面的,但是我们可以用以下模式来总结:

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

错误值转换为Number,遵循C语言中有意义的内容:nullfalse都是0。""变为0并不完全符合这个约定,但对我来说足够有意义。
因此,我认为,如果您正在验证用户输入,一元加号除了接受小数外,对所有内容都有正确的行为(但在我的真实的情况中,我更感兴趣的是捕捉电子邮件输入,而不是userId、完全省略的值等),而parseInt则过于自由。

3duebb1j

3duebb1j6#

注意,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));

相关问题