When I looked at the solutions in the other answers I saw some things that I know are bad for performance.(当我在其他答案中查看解决方案时,我看到一些我知道对性能有害的事情。)
I was going to put them in a comment but I thought it was better to benchmark it and share the results.(我打算将它们放在评论中,但我认为最好对它进行基准测试并分享结果。) You can test it yourself .(你可以自己测试一下 。) Below are my results (ymmv) normalized after the fastest operation in each browser (multiply the 1.0 time with the normalized value to get the absolute time in ms).(下面是我的结果(ymmv)在每个浏览器中最快的操作之后归一化(将1.0时间乘以标准化值以获得以ms为单位的绝对时间)。)
Chrome Firefox Opera MSIE Safari Node
-------------------------------------------------------------------
1.0 time 37ms 73ms 68ms 184ms 73ms 21ms
if-immediate 1.0 1.0 1.0 2.6 1.0 1.0
if-indirect 1.2 1.8 3.3 3.8 2.6 1.0
switch-immediate 2.0 1.1 2.0 1.0 2.8 1.3
switch-range 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
switch-indirect-array 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
Test where performed on Windows 7 32bit with the folowing versions: Chrome 21.0.1180.89m , Firefox 15.0 , Opera 12.02 , MSIE 9.0.8112 , Safari 5.1.7 .(使用以下版本测试在Windows 7 32位上执行的操作: Chrome 21.0.1180.89m , Firefox 15.0 , Opera 12.02 , MSIE 9.0.8112 , Safari 5.1.7 。) Node was run on a Linux 64bit box because the timer resolution on Node.js for Windows was 10ms instead of 1ms.(节点在Linux 64位盒上运行,因为Node.js for Windows上的计时器分辨率是10ms而不是1ms。)
if-immediate(如果,即时)
This is the fastest in all tested environments, except in ... drumroll MSIE!(这是所有测试环境中最快的,除了...... 鼓乐 MSIE!) (surprise, surprise).((惊讶,惊讶)。) This is the recommended way to implement it.(这是实现它的推荐方法。)
if (val < 1000) { /*do something */ } else
if (val < 2000) { /*do something */ } else
...
if (val < 30000) { /*do something */ } else
if-indirect(如果间接)
This is a variant of switch-indirect-array
but with if
-statements instead and performs much faster than switch-indirect-array
in almost all tested environments.(这是switch-indirect-array
一种变体,但使用if
-statements代替,并且在几乎所有测试环境中执行速度比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
switch-immediate(开关,立即)
This is pretty fast in all tested environments, and actually the fastest in MSIE.(这在所有测试环境中都非常快,实际上是MSIE中最快的。) It works when you can do a calculation to get an index.(它可以在您进行计算以获取索引时起作用。)
switch (Math.floor(val/1000)) {
case 0: /* do something */ break;
case 1: /* do something */ break;
...
case 29: /* do something */ break;
}
switch-range(开关范围)
This is about 6 to 40 times slower than the fastest in all tested environments except for Opera where it takes about one and a half times as long.(这比所有测试环境中最快的速度慢6到40倍,除了Opera需要大约1.5倍的时间。) It is slow because the engine has to compare the value twice for each case.(它很慢,因为引擎必须为每种情况比较两次值。) Surprisingly it takes Chrome almost 40 times longer to complete this compared to the fastest operation in Chrome, while MSIE only takes 6 times as long.(令人惊讶的是,与Chrome中最快的操作相比,Chrome完成此操作所需的时间要长近40倍,而MSIE只需要6倍的时间。) But the actual time difference was only 74ms in favor to MSIE at 1337ms(!).(但实际时差仅为74毫秒,有利于MSIE为1337毫秒(!)。)
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;
}
switch-range2(开关范围2)
This is a variant of switch-range
but with only one compare per case and therefore faster, but still very slow except in Opera.(这是switch-range
一种变体,但每种情况只有一个比较,因此速度更快,但除了Opera之外仍然很慢。) The order of the case statement is important since the engine will test each case in source code order ECMAScript262:5 12.11(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;
}
switch-indirect-array(切换-间接阵列)
In this variant the ranges is stored in an array.(在该变体中,范围存储在阵列中。) This is slow in all tested environments and very slow in Chrome.(这在所有测试环境中都很慢,而在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;
}
array-linear-search(阵列线性搜索)
This is a combination of a linear search of values in an array, and the switch statement with fixed values.(这是对数组中值的线性搜索和具有固定值的switch语句的组合。) The reason one might want to use this is when the values isn't known until runtime.(人们可能想要使用它的原因是直到运行时才知道这些值。) It is slow in every tested environment, and takes almost 10 times as long in MSIE.(在每个测试环境中都很慢,在MSIE中需要几乎10倍的时间。)
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-binary-switch(阵列二进制开关)
This is a variant of array-linear-switch
but with a binary search.(这是array-linear-switch
的变体,但具有二进制搜索。) Unfortunately it is slower than the linear search.(不幸的是它比线性搜索慢。) I don't know if it is my implementation or if the linear search is more optimized.(我不知道这是我的实现还是线性搜索更优化。) It could also be that the keyspace is to small.(它也可能是键空间很小。)
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;
}
Conclusion(结论)
If performance is important, use if
-statements or switch
with immediate values.(如果性能很重要,请使用if
-statements或switch
为立即值。) 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…