parseInt vs unary plus เมื่อไรจะใช้อันไหน


149

อะไรคือความแตกต่างระหว่างบรรทัดนี้:

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

และสายนี้

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

การทดสอบ jsperfนี้แสดงให้เห็นว่าโอเปอเรเตอร์ unary นั้นเร็วกว่ามากในรุ่นโครมปัจจุบันโดยสมมติว่ามันใช้สำหรับ node.js !?

ถ้าฉันพยายามแปลงสตริงที่ไม่ใช่ตัวเลขทั้งสองคืนNaN:

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

ดังนั้นเมื่อไรฉันจึงควรใช้งานparseIntมากกว่า unary plus (โดยเฉพาะใน node.js) ???

แก้ไข : และผู้ประกอบการตัวหนอนสองตัวที่แตกต่างกัน~~คืออะไร?


1
เกณฑ์มาตรฐานjsperf.com/parseint-vs-unary-operator
Roko C. Buljan

คำตอบ:


169

โปรดดูคำตอบนี้สำหรับกรณีที่สมบูรณ์มากขึ้น




นี่คือความแตกต่างเล็กน้อยที่ฉันรู้:

  • สตริงที่ว่างเปล่า""ประเมินไป0ในขณะที่ประเมินว่ามันparseInt NaNIMO NaNสตริงว่างเปล่าควรจะเป็น

    +'' === 0;              //true
    isNaN(parseInt('',10)); //true
  • เอกภาพ+ทำหน้าที่คล้ายกันมากขึ้นparseFloatเพราะมันยังยอมรับทศนิยม

    parseIntบนมืออื่น ๆ .หยุดการแยกเมื่อเห็นตัวละครที่ไม่ใช่ตัวเลขเช่นระยะเวลาที่มีวัตถุประสงค์เพื่อเป็นจุดทศนิยม

    +'2.3' === 2.3;           //true
    parseInt('2.3',10) === 2; //true
  • parseIntและparseFloatจะแยกวิเคราะห์และสร้างสตริงจากซ้ายไปขวา หากพวกเขาเห็นอักขระที่ไม่ถูกต้องมันจะส่งคืนสิ่งที่ถูกวิเคราะห์คำ (ถ้ามี) เป็นตัวเลขและNaNหากไม่มีการแยกวิเคราะห์เป็นตัวเลข

    unary +ในอีกทางหนึ่งจะส่งคืนNaNถ้าสตริงทั้งหมดไม่สามารถแปลงเป็นตัวเลขได้

    parseInt('2a',10) === 2; //true
    parseFloat('2a') === 2;  //true
    isNan(+'2a');            //true
  • เท่าที่เห็นในความคิดเห็นของ@ Alex เค , 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.

6
นอกจากนี้เมื่อใช้ Radix+"0xf" != parseInt("0xf", 10)
Alex K.

ฉันชอบคำตอบของคุณมากที่สุดคุณสามารถอธิบายความแตกต่างของผู้ดำเนินการตัวหนอนสองตัวได้ไหม ~~ คืออะไร?
hereandnow78

@ hereandnow78 ที่จะได้รับการอธิบายที่นี่ มันเทียบเท่าระดับบิตMath.floor()ซึ่งโดยทั่วไปจะตัดส่วนทศนิยมออก
Joseph

4
ที่จริงแล้วไม่ได้เป็นตัวแทนที่ถูกต้องสำหรับจำนวนเต็ม"2e3" 2000มันเป็นเลขทศนิยมที่ถูกต้องแม้ว่า: parseFloat("2e3")จะให้ผลถูกต้อง2000ตามคำตอบ และ"0xf"ต้องการอย่างน้อยฐาน 16 ซึ่งเป็นเหตุผลว่าทำไมparseInt("0xf", 10)ผลตอบแทน0ในขณะที่parseInt("0xf", 16)ส่งกลับค่า 15 คุณคาดหวัง
บาร์ต

2
@Joseph the Dreamer และ @ hereandnow78: เครื่องหมายตัวหนอนคู่ตัดส่วนทศนิยมของตัวเลขในขณะที่ Math.floor จะส่งกลับตัวเลขที่ต่ำกว่าที่ใกล้เคียงที่สุด พวกเขาทำงานเหมือนกันสำหรับจำนวนบวก แต่และMath.floor(-3.5) == -4 ~~-3.5 == -3
Albin

261

ตารางการแปลงใด ๆ ก็ตามที่มีหมายเลขที่สุดยอด: ตารางการแปลง


2
กรุณาเพิ่มลง"NaN"ในตารางนี้
chharvey

มันอาจจะมีมูลค่าเพิ่มisNaNคอลัมน์ตารางนี้: ยกตัวอย่างเช่นisNaN("")เป็นเท็จ (คือมันถือว่าเป็นจำนวนมาก) แต่parseFloat("")เป็นNaNที่สามารถ gotcha ถ้าคุณกำลังพยายามที่จะใช้isNaNในการตรวจสอบการป้อนข้อมูลก่อนที่จะผ่านมันไปparseFloat
Retsam

คุณควรเพิ่ม'{valueOf: function(){return 42}, toString: function(){return "56"}}'ในรายการ ผลการผสมที่น่าสนใจ
murrayju

3
ดังนั้นบทสรุปของตารางคือ+การเขียนที่สั้นกว่าNumberและ furter เป็นวิธีที่บ้าที่จะทำมันล้มเหลวในกรณีของขอบ?
Mihail Malostanidis

[] .undef สิ่งหรือเป็นเพียงวิธีการสร้างไม่ได้กำหนด? ไม่พบบันทึกของ "undef" ที่เกี่ยวข้องกับ JS ผ่าน Google
jcairney

10

ตารางในคำตอบของ thg435 ฉันเชื่อว่าครอบคลุม แต่เราสามารถสรุปด้วยรูปแบบต่อไปนี้:

  • ยูนารีพลัสไม่ได้ปฏิบัติต่อค่าที่ผิดทั้งหมดเหมือนกัน
  • เอกบวกส่งtrueไป 1 แต่จะ"true"NaN
  • ในทางกลับกันparseIntก็มีเสรีมากขึ้นสำหรับสตริงที่ไม่ใช่ตัวเลขที่บริสุทธิ์ parseInt('123abc') === 123ในขณะที่รายงาน+NaN
  • Numberจะยอมรับตัวเลขทศนิยมที่ถูกต้องในขณะที่parseIntลดลงทุกอย่างผ่านทศนิยม ดังนั้นparseIntเลียนแบบพฤติกรรม C แต่อาจไม่เหมาะสำหรับการประเมินอินพุตของผู้ใช้
  • ทั้งตัดช่องว่างในสตริง
  • parseIntเป็นตัวแยกวิเคราะห์ที่ออกแบบมาไม่ดียอมรับอินพุตแปดและฐานสิบหก เอกภาพบวกใช้เวลาเพียงเฮกซะเคมี

ค่า Falsy แปลงเป็นค่าที่Numberตามมาใน C: nullและfalseทั้งคู่เป็นศูนย์ ""ไปที่ 0 ไม่ได้ทำตามอนุสัญญานี้ แต่สมเหตุสมผลสำหรับฉัน

ดังนั้นฉันคิดว่าถ้าคุณกำลังตรวจสอบการป้อนข้อมูลของผู้ใช้ unary plus มีพฤติกรรมที่ถูกต้องสำหรับทุกอย่างยกเว้นมันรับทศนิยม parseInt มีแนวคิดเสรีเกินไป


2
"Unary plus ใช้เลขฐานสิบหกเท่านั้น" คุณหมายถึงทศนิยมหรือไม่
krillgar

0

ระวัง, parseInt เร็วกว่า + ตัวดำเนินการ unary ในโหนด 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เต้น unary plus บน iOS :) สิ่งนี้มีประโยชน์สำหรับเว็บแอปที่มีการใช้ CPU มากเท่านั้น ในฐานะกฎของหัวแม่มือฉันแนะนำให้ JS opt-guys พิจารณาผู้ให้บริการ JS มากกว่าอีกคนหนึ่งจากมุมมองประสิทธิภาพมือถือในปัจจุบัน

ดังนั้นไปที่มือถือก่อน ;)


ตามที่โพสต์อื่น ๆ อธิบายว่าพวกเขาทำสิ่งที่แตกต่างกันมากดังนั้นคุณไม่สามารถสลับหนึ่งสำหรับอื่น ๆ ...
Bergi

@Bergi ใช่มั้ย แต่พวกเขาก็มีอะไรเหมือนกันมากมาย บอกวิธีแก้ปัญหาด้านประสิทธิภาพหนึ่งตัวใน JavaScript ว่าเป็นตัวเลือกที่ถูกต้องหรือไม่ โดยทั่วไปนั่นเป็นสาเหตุที่กฎของหัวแม่มืออยู่ที่นั่นสำหรับเรา ส่วนที่เหลือเป็นงานเฉพาะ
Arman McHitarian

3
@ArmanMcHitaryan นี่คือ microoptimisation ที่ไร้ประโยชน์และมันไม่คุ้มค่า ตรวจสอบบทความนี้ - fabien.potencier.org/article/8/…
webvitaly

@webvitaly บทความดีๆ มีพวกที่มุ่งเน้นไปที่คนที่ชอบเขียนโค้ด "เร็วที่สุด" และในบางโครงการที่ไม่เลว นั่นเป็นเหตุผลที่ฉันพูดถึง "JS เลือกคนที่จะต้องพิจารณา" นี่ไม่ใช่แน่นอนต้อง :) แต่ฉันเองก็พบว่ามันอ่านได้มากขึ้นนอกจากนี้
Arman McHitarian

คุณมีหนังเรื่องนี้ไหม? ลิงก์ของคุณเสีย
djechlin
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.