当我查看其他答案中的解决方案时,我看到了一些我知道对性能不利的事情。我打算将它们放在评论中,但我认为最好对其进行基准测试并分享结果。你可以自己测试一下。以下是我在每个浏览器中以最快速度运行后标准化的结果 (ymmv)。
这是 2021-MAY-05 的结果
测试 |
铬合金 |
火狐 |
歌剧 |
边缘 |
勇敢的 |
节点 |
1.0 次 |
15 毫秒 |
14 毫秒 |
17 毫秒 |
17 毫秒 |
16 毫秒 |
14 毫秒 |
如果立即 |
1.00 |
1.00 |
1.00 |
1.00 |
1.00 |
1.00 |
如果-间接 |
2.20 |
1.21 |
2.06 |
2.18 |
2.19 |
1.93 |
立即切换 |
2.07 |
1.43 |
1.71 |
1.71 |
2.19 |
1.93 |
开关量程 |
3.60 |
2.00 |
2.47 |
2.65 |
2.88 |
2.86 |
开关范围2 |
2.07 |
1.36 |
1.82 |
1.71 |
1.94 |
1.79 |
开关间接阵列 |
2.93 |
1.57 |
2.53 |
2.47 |
2.75 |
2.50 |
阵列线性开关 |
2.73 |
3.29 |
2.12 |
2.12 |
2.38 |
2.50 |
阵列二进制开关 |
5.80 |
6.07 |
5.24 |
5.24 |
5.44 |
5.37 |
2021 年的测试在 64 位 Windows 10 上执行,使用以下版本:Chrome 90.0.4430.212、Firefox 89.0b13、Opera 76.0.4017.123、Edge 90.0.818.62、Brave 1.24.SL8016下运行和Node.816 s.1
Apple 没有为 Windows更新Safari,所以它仍然是 5.1.7。我在这次测试中将其更改为 Brave。
以下是 2012 年 9 月 4 日的结果,用于历史比较:
测试 |
铬合金 |
火狐 |
歌剧 |
微信公众平台 |
苹果浏览器 |
节点 |
1.0 次 |
37 毫秒 |
73 毫秒 |
68 毫秒 |
184 毫秒 |
73 毫秒 |
21 毫秒 |
如果立即 |
1.0 |
1.0 |
1.0 |
2.6 |
1.0 |
1.0 |
如果-间接 |
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 |
开关范围2 |
31.9 |
8.3 |
2.0 |
4.5 |
9.5 |
6.9 |
开关间接阵列 |
35.2 |
9.6 |
4.2 |
5.5 |
10.7 |
8.6 |
阵列线性开关 |
3.6 |
4.1 |
4.5 |
10.0 |
4.7 |
2.7 |
阵列二进制开关 |
7.8 |
6.7 |
9.5 |
16.0 |
15.0 |
4.9 |
2012 年的测试在 32 位 Windows 7 上执行,使用以下版本:Chrome 21.0.1180.89m、Firefox 15.0、Opera 12.02、MSIE 9.0.8112、Safari 5.1.7。Node在 Linux 64 位机器上运行,因为 Node for Windows 上的计时器分辨率是 10 毫秒而不是 1 毫秒。
如果立即
这是所有测试环境中最快的方法,除了...鼓声MSIE!(惊喜,惊喜)。
这是实现它的推荐方法。
if (val < 1000) { /*do something */ } else
if (val < 2000) { /*do something */ } else
...
if (val < 30000) { /*do something */ } else
如果-间接
这是switch-indirect-array
but with if
-statements的变体,在所有测试引擎中速度更快。
2021 年,它比最快的测试慢 20-120%(2012 年:0-280%)。Chrome 2021 (2.20) 比 2012 (1.2) 需要更长的时间
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
立即切换
当您可以进行计算以获取索引时,这会起作用。
在 2021 年,它比 慢 40-120%(2012 年:0-180%)if-immediate
,除了在 MSIE 中它实际上是最快的。
switch (Math.floor(val/1000)) {
case 0: /* do something */ break;
case 1: /* do something */ break;
...
case 29: /* do something */ break;
}
开关量程
它很慢,因为引擎必须为每种情况比较两次值。
2021 年,它比最快的测试慢 1-2.6(2012 年:1.6-38)倍。Chrome 从 38 到 3.6 的改进最大,但仍然是最慢的测试引擎。
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
但每个案例只有一个比较,因此速度更快。case 语句的顺序很重要,因为引擎将按照源代码顺序测试每个 case ECMAScript 2020 13.12.9
在 2021 年,它比最快的测试慢 36-107%,但在 2012 年,它慢了 1-31 倍。本次测试中表现最差的依然是Chrome,但从32倍提升到了2倍。
switch (true) {
case (val < 1000): /* do something */ break;
case (val < 2000): /* do something */ break;
...
case (val < 30000): /* do something */ break;
}
开关间接阵列
在这个变体中,范围存储在一个数组中。
2021 年,它比最快的测试慢 57-193%(2012 年:3-35 倍)。所有测试引擎的性能都有所提高,虽然 Chrome 仍然是最慢的,但它已从 35 提高到 2.93。
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;
}
数组线性搜索
在这个变体中,范围存储在一个数组中。
2021 年,它比最快的测试慢 57-193%(2012 年:3-35 倍)。所有测试引擎的性能都有所提高,虽然 Chrome 仍然是最慢的,但它已从 35 提高到 2.93。
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
但带有二分搜索。不幸的是,它比线性搜索慢。不知道是我的实现还是线性搜索更优化了。也可能是键空间太小。
在 2021 年,这慢了 4-5(2012 年:4-16)倍。不要使用.
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
-statements 或switch
。