เมื่อฉันดูวิธีแก้ปัญหาในคำตอบอื่น ๆ ฉันเห็นบางสิ่งที่ฉันรู้ว่าไม่ดีต่อประสิทธิภาพ ฉันจะใส่พวกเขาในความคิดเห็น แต่ฉันคิดว่ามันจะเป็นการดีกว่าที่จะทำการเปรียบเทียบและแบ่งปันผลลัพธ์ คุณสามารถทดสอบได้ด้วยตัวคุณเอง ด้านล่างคือผลลัพธ์ของฉัน (ymmv) ที่ทำให้เป็นมาตรฐานหลังจากการดำเนินการที่เร็วที่สุดในแต่ละเบราว์เซอร์ (คูณ 1.0 ครั้งด้วยค่าปกติเพื่อให้ได้เวลาสัมบูรณ์เป็น ms)
Chrome Firefox Opera MSIE Safari โหนด
-------------------------------------------------- -----------------
1.0 เวลา 37ms 73ms 68ms 184ms 73ms 21ms
if-ทันที 1.0 1.0 1.0 2.6 1.0 1.0
if-อ้อม 1.2 1.8 3.3 3.8 2.6 1.0
สวิตช์ทันที 2.0 1.1 2.0 1.0 2.8 1.3
ช่วงสวิตช์ 38.1 10.6 2.6 7.3 20.9 10.4
switch-range2 31.9 8.3 2.0 4.5 9.5 6.9
สวิตช์แบบอ้อมอาร์เรย์ 35.2 9.6 4.2 5.5 10.7 8.6
array-linear-switch 3.6 4.1 4.5 10.0 4.7 2.7
array-binary-switch 7.8 6.7 9.5 16.0 15.0 4.9
การทดสอบที่ดำเนินการบน Windows 7 32bit กับรุ่น folowing: Chrome 21.0.1180.89m , Firefox 15.0 , Opera 12.02 , MSIE 9.0.8112 , Safari 5.1.7 โหนดถูกเรียกใช้บนกล่อง Linux 64 บิตเนื่องจากความละเอียดของตัวจับเวลาใน Node.js สำหรับ Windows คือ 10 มิลลิเซคอนแทนที่จะเป็น 1 มิลลิวินาที
ถ้า-ทันที
นี่เป็นวิธีที่เร็วที่สุดในทุกสภาพแวดล้อมที่ทดสอบยกเว้นใน ... drumroll MSIE! (ประหลาดใจประหลาดใจ) นี่เป็นวิธีที่แนะนำให้ใช้
if (val < 1000) { /*do something */ } else
if (val < 2000) { /*do something */ } else
...
if (val < 30000) { /*do something */ } else
ถ้า-ทางอ้อม
นี่เป็นตัวแปรหนึ่งของswitch-indirect-array
แต่ด้วย - สถานะif
แทนและทำงานได้เร็วกว่าswitch-indirect-array
ในสภาพแวดล้อมที่ทดสอบเกือบทั้งหมด
values=[
1000, 2000, ... 30000
];
if (val < values[0]) { /* do something */ } else
if (val < values[1]) { /* do something */ } else
...
if (val < values[29]) { /* do something */ } else
สวิทช์ทันที
นี่ค่อนข้างเร็วในทุกสภาพแวดล้อมที่ทดสอบและจริง ๆ แล้วเร็วที่สุดใน MSIE มันทำงานได้เมื่อคุณสามารถทำการคำนวณเพื่อรับดัชนี
switch (Math.floor(val/1000)) {
case 0: /* do something */ break;
case 1: /* do something */ break;
...
case 29: /* do something */ break;
}
สวิทช์ช่วง
นี่จะช้ากว่าเร็วที่สุดประมาณ 6 ถึง 40 เท่าในสภาพแวดล้อมการทดสอบทั้งหมดยกเว้น Opera ที่ใช้เวลาประมาณหนึ่งและครึ่งเท่า มันช้าเพราะเครื่องยนต์จะต้องเปรียบเทียบค่าสองครั้งสำหรับแต่ละกรณี น่าแปลกที่ Chrome ใช้เวลานานกว่าเกือบ 40 เท่าในการดำเนินการนี้เมื่อเทียบกับการทำงานที่รวดเร็วที่สุดใน Chrome ขณะที่ MSIE ใช้เวลาเพียง 6 ครั้งเท่านั้น แต่ความแตกต่างของเวลาที่แท้จริงนั้นอยู่ที่ 74ms สำหรับ MSIE ที่ 1337ms (!)
switch (true) {
case (0 <= val && val < 1000): /* do something */ break;
case (1000 <= val && val < 2000): /* do something */ break;
...
case (29000 <= val && val < 30000): /* do something */ break;
}
สวิทช์ช่วงที่ 2
นี่คือตัวแปรของswitch-range
แต่มีเพียงหนึ่งเปรียบเทียบต่อกรณีและดังนั้นจึงเร็วกว่า แต่ก็ยังช้ามากยกเว้นใน Opera ลำดับของคำสั่ง case มีความสำคัญเนื่องจากเครื่องยนต์จะทดสอบแต่ละเคสในการสั่งซื้อซอร์สโค้ดECMAScript262: 5 12.11
switch (true) {
case (val < 1000): /* do something */ break;
case (val < 2000): /* do something */ break;
...
case (val < 30000): /* do something */ break;
}
สวิทช์ทางอ้อมอาร์เรย์
ในตัวแปรนี้ช่วงจะถูกเก็บไว้ในอาร์เรย์ สิ่งนี้ช้าในทุกสภาพแวดล้อมที่ทดสอบและช้ามากใน Chrome
values=[1000, 2000 ... 29000, 30000];
switch(true) {
case (val < values[0]): /* do something */ break;
case (val < values[1]): /* do something */ break;
...
case (val < values[29]): /* do something */ break;
}
อาร์เรย์เชิงเส้นค้นหา
นี่คือการรวมกันของการค้นหาเชิงเส้นของค่าในอาร์เรย์และคำสั่งสวิทช์ที่มีค่าคงที่ เหตุผลที่อาจต้องการใช้สิ่งนี้คือเมื่อไม่ทราบค่าจนกว่าจะถึงเวลารันไทม์ มันช้าในทุกสภาพแวดล้อมที่ทดสอบและใช้เวลาเกือบ 10 เท่าใน MSIE
values=[1000, 2000 ... 29000, 30000];
for (sidx=0, slen=values.length; sidx < slen; ++sidx) {
if (val < values[sidx]) break;
}
switch (sidx) {
case 0: /* do something */ break;
case 1: /* do something */ break;
...
case 29: /* do something */ break;
}
อาร์เรย์ไบนารีสวิทช์
นี่คือตัวแปรของarray-linear-switch
แต่ด้วยการค้นหาแบบไบนารี น่าเสียดายที่มันช้ากว่าการค้นหาเชิงเส้น ฉันไม่รู้ว่าเป็นการใช้งานของฉันหรือไม่หรือการค้นหาแบบเชิงเส้นเหมาะสมที่สุด อาจเป็นไปได้ว่า keyspace มีขนาดเล็ก
values=[0, 1000, 2000 ... 29000, 30000];
while(range) {
range = Math.floor( (smax - smin) / 2 );
sidx = smin + range;
if ( val < values[sidx] ) { smax = sidx; } else { smin = sidx; }
}
switch (sidx) {
case 0: /* do something */ break;
...
case 29: /* do something */ break;
}
ข้อสรุป
หากประสิทธิภาพมีความสำคัญให้ใช้ - สถานะif
หรือswitch
ด้วยค่าทันที