parseInt vs一元加,什么时候使用?


149

这行之间有什么区别:

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

这条线

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

jsperf测试表明,假设适用于node.js !,在当前的chrome版本中,一元运算符要快得多。

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

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

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

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


Answers:


169

请参阅此答案以获得更完整的案例集




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

  • 空字符串的""计算结果为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.
    

6
同样在使用基数时+"0xf" != parseInt("0xf", 10)
Alex K.

到目前为止,我最喜欢您的回答,您还能解释一下双波浪号运算符~~有什么区别吗?
hereandnow78 2013年

@ hereandnow78这将在这里解释。它与的按位等效Math.floor(),基本上会舍去小数部分。
约瑟夫

4
实际上,"2e3"不是有效的整数表示形式2000。但是,它是一个有效的浮点数:parseFloat("2e3")将正确地给出2000答案。并且"0xf"要求至少以16为底,这就是为什么parseInt("0xf", 10)return 0,而parseInt("0xf", 16)返回您期望的值15的原因。
巴特2013年

2
@梦想家约瑟夫(Joseph the Dreamer)和@ hereandnow78:双波浪号可截断数字的小数部分,而Math.floor返回最接近的较低数字。对于正数,它们的作用相同,但是Math.floor(-3.5) == -4~~-3.5 == -3
阿尔宾

261

最终的数字转换表: 换算表


2
请添加"NaN"到此表中。
chharvey 2014年

这可能是值得加入的isNaN列到这个表:比如,isNaN("")是假的(也就是它被认为是一个数字),但parseFloat("")NaN,它可以是一个疑难杂症,如果你想用isNaN它传递给前验证输入parseFloat
Retsam

您还应该添加'{valueOf: function(){return 42}, toString: function(){return "56"}}'到列表中。混合的结果很有趣。
murrayju

3
因此,表格的摘要是这+只是一种较短的书写方式Number,而表格的摘要只是一些疯狂的方式而在边缘情况下失败了?
Mihail Malostanidis

[] .undef是一件事,还是只是生成undefined的任意方式?通过Google找不到与JS相关的“ undef”的任何记录。
jcairney

10

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

  • 一元加号不会将所有伪造的值都一样对待,但是它们全都是伪造的。
  • 一元加发送true至1,但发送"true"NaN
  • 另一方面,parseInt对于不是纯数字的字符串,它更为自由。 parseInt('123abc') === 123,而+报告NaN
  • Number将接受有效的十进制数字,而parseInt只删除所有超出十进制的数字。因此parseInt模拟C行为,但对于评估用户输入可能不是理想的。
  • 两者都修剪字符串中的空格。
  • parseInt解析器设计不良,它接受八进制和十六进制输入。一元加号仅需十六进制。

虚假值转换为Number遵循C:中有意义的值, null并且false均为零。 ""设为0并不太遵循这个约定,但是对我来说足够有意义。

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


2
“一元加号仅需要十六进制”是不是十进制?
krillgar

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));

-3

也要考虑性能。令我感到惊讶的是,parseInt在iOS上胜过一进制:)这仅对CPU消耗大的Web应用程序有用。作为一个经验法则,我建议JS opt-guys从当今的移动性能角度考虑将JS运算符放在另一个运算符上。

因此,请先移动版 ;)


正如其他帖子解释的那样,他们做的事情大不相同,因此您不能轻易地将彼此交换……
Bergi

@Bergi,对,但是它们也有很多共同点。告诉我一个绝对不是唯一正确选择的JavaScript性能解决方案吗?总的来说,这就是为什么我们要遵循经验法则的原因。其余的是特定于任务的。
阿曼·麦克希塔里安

3
@ArmanMcHitaryan这是无用的微优化,它不值得。看看这篇文章- fabien.potencier.org/article/8/...
webvitaly

@webvitaly,不错的文章。总是有一些非常注重性能的人,他们喜欢编写“最快的”代码,在一些特定的项目中也不错。这就是为什么我提到“要考虑的JS选择人”的原因。当然,这不是必须的:),但是我自己也发现它更具可读性。
Arman McHitarian 2013年

你为此被引用吗?您的链接已损坏。
djechlin '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.