当我查看其他答案中的解决方案时,我看到了一些我知道对性能不利的事情。我打算把它们放在评论中,但我认为最好对它进行基准测试并分享结果。您可以自己测试。以下是在每个浏览器中执行最快操作后归一化的结果(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年的测试在Windows 10 64bit上执行,具有以下版本:Chrome 90.0.4430.212,Firefox 89.0b13,Opera 76.0.4017.123,Edge 90.0.818.62,Brave 1.24.85和Node 16.1.0(在WSL下运行)
苹果没有更新Windows版Safari,所以它仍然是5.1.7。在这个测试中,我把它改成了勇敢。
以下是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年的测试在Windows 7 32bit上进行,版本如下:Chrome 21.0.1180.89m,Firefox 15.0,Opera 12.02,MSIE 9.0.8112,Safari 5.1.7。Node在Linux 64bit机器上运行,因为Node for Windows上的计时器分辨率是10ms而不是1ms。
如果-立即
这是所有测试环境中最快的方法,除了...鼓点嗯!(惊喜,惊喜)。
这是实现它的推荐方法。
if (val < 1000) { /*do something */ } else
if (val < 2000) { /*do something */ } else
...
if (val < 30000) { /*do something */ } else
如果-间接
这是但带有 -语句的变体,并且在所有测试的引擎中都更快。switch-indirect-array
if
在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%),除了在MSIE中它实际上是最快的。if-immediate
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
这是的变体,但每个案例只有一个比较,因此更快。case 语句的顺序很重要,因为引擎将按照源代码顺序测试每个案例 ECMAScript 2020 13.12.9switch-range
在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
switch