Khi tôi nhìn vào các giải pháp trong các câu trả lời khác, tôi thấy một số điều mà tôi biết là không tốt cho hiệu suất. Tôi sẽ đưa chúng vào một bình luận nhưng tôi nghĩ sẽ tốt hơn nếu đánh giá nó và chia sẻ kết quả. Bạn có thể tự kiểm tra nó . Dưới đây là kết quả của tôi (ymmv) được chuẩn hóa sau thao tác nhanh nhất trong mỗi trình duyệt (nhân thời gian 1.0 với giá trị chuẩn hóa để có thời gian tuyệt đối tính bằng ms).
Chrome Firefox Opera MSIE Safari Nút
-------------------------------------------------- -----------------
1,0 thời gian 37ms 73ms 68ms 184ms 73ms 21ms
if-ngay 1.0 1.0 1.0 2.6 1.0 1.0
if-gián tiếp 1.2 1.8 3.3 3.8 2.6 1.0
chuyển đổi ngay lập tức 2.0 1.1 2.0 1.0 2.8 1.3
phạm vi chuyển đổi 38.1 10.6 2.6 7.3 20.9 10.4
chuyển đổi phạm vi2 31.9 8.3 2.0 4.5 9.5 6.9
chuyển mạch-gián tiếp-mảng 35.2 9.6 4.2 5.5 10.7 8.6
mảng-tuyến tính-chuyển đổi 3.6 4.1 4.5 10.0 4.7 2.7
mảng-nhị phân-chuyển đổi 7.8 6.7 9.5 16.0 15.0 4.9
Kiểm tra nơi thực hiện trên Windows 7 32 bit với các phiên bản folowing: Chrome 21.0.1180.89m , Firefox 15.0 , Opera 12.02 , MSIE 9.0.8112 , Safari 5.1.7 . Node được chạy trên hộp Linux 64 bit vì độ phân giải hẹn giờ trên Node.js cho Windows là 10ms thay vì 1ms.
nếu ngay lập tức
Đây là tốc độ nhanh nhất trong tất cả các môi trường được thử nghiệm, ngoại trừ trong ... MSIE trống ! (ngạc nhiên, ngạc nhiên). Đây là cách được khuyến nghị để thực hiện nó.
if (val < 1000) { /*do something */ } else
if (val < 2000) { /*do something */ } else
...
if (val < 30000) { /*do something */ } else
nếu-gián tiếp
Đây là một biến thể của switch-indirect-array
nhưng với if
-statements thay vào đó và thực hiện nhanh hơn nhiều so với switch-indirect-array
hầu hết các môi trường được thử nghiệm.
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
chuyển đổi ngay lập tức
Điều này khá nhanh trong tất cả các môi trường được thử nghiệm và thực sự là nhanh nhất trong MSIE. Nó hoạt động khi bạn có thể thực hiện một phép tính để lấy chỉ mục.
switch (Math.floor(val/1000)) {
case 0: /* do something */ break;
case 1: /* do something */ break;
...
case 29: /* do something */ break;
}
phạm vi chuyển đổi
Tốc độ này chậm hơn khoảng 6 đến 40 lần so với tốc độ nhanh nhất trong tất cả các môi trường được thử nghiệm ngoại trừ Opera, nơi nó mất khoảng một lần rưỡi thời gian. Nó chậm vì động cơ phải so sánh giá trị hai lần cho mỗi trường hợp. Đáng ngạc nhiên là Chrome phải mất gần 40 lần để hoàn thành việc này so với thao tác nhanh nhất trong Chrome, trong khi MSIE chỉ mất 6 lần thời gian. Nhưng chênh lệch thời gian thực tế chỉ là 74ms nghiêng về MSIE ở mức 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;
}
chuyển đổi phạm vi2
Đây là một biến thể của switch-range
nhưng chỉ có một so sánh cho mỗi trường hợp và do đó nhanh hơn, nhưng vẫn rất chậm, ngoại trừ trong Opera. Thứ tự của câu lệnh tình huống rất quan trọng vì động cơ sẽ kiểm tra từng trường hợp theo thứ tự mã nguồn ECMAScript262: 5 12.11
switch (true) {
case (val < 1000): /* do something */ break;
case (val < 2000): /* do something */ break;
...
case (val < 30000): /* do something */ break;
}
chuyển-gián tiếp-mảng
Trong biến thể này, các phạm vi được lưu trữ trong một mảng. Điều này chậm trong tất cả các môi trường được thử nghiệm và rất chậm trong 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;
}
mảng tuyến tính-tìm kiếm
Đây là sự kết hợp của tìm kiếm tuyến tính các giá trị trong một mảng và câu lệnh switch với các giá trị cố định. Lý do người ta có thể muốn sử dụng điều này là khi các giá trị không được biết cho đến khi chạy. Nó chậm trong mọi môi trường được thử nghiệm và mất gần 10 lần trong 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;
}
mảng nhị phân-chuyển đổi
Đây là một biến thể của array-linear-switch
nhưng với một tìm kiếm nhị phân. Thật không may, nó chậm hơn so với tìm kiếm tuyến tính. Tôi không biết nếu đó là triển khai của tôi hoặc nếu tìm kiếm tuyến tính được tối ưu hóa hơn. Nó cũng có thể là không gian phím là nhỏ.
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;
}
Phần kết luận
Nếu hiệu suất là quan trọng, sử dụng if
-statements hoặc switch
với các giá trị ngay lập tức.