所以我想用这样的switch语句:
switch (scrollLeft) {
case (<1000):
//do stuff
break;
case (>1000 && <2000):
//do stuff
break;
}
现在我知道这些语句(<1000)或(>1000 && <2000)中的任何一个都不会工作(显然是由于不同的原因)。我问的是最有效的方法。我讨厌使用30个if语句,所以我宁愿使用switch语法。我能做些什么吗?
所以我想用这样的switch语句:
switch (scrollLeft) {
case (<1000):
//do stuff
break;
case (>1000 && <2000):
//do stuff
break;
}
现在我知道这些语句(<1000)或(>1000 && <2000)中的任何一个都不会工作(显然是由于不同的原因)。我问的是最有效的方法。我讨厌使用30个if语句,所以我宁愿使用switch语法。我能做些什么吗?
当前回答
更新已接受的答案(还不能评论)。截至2016年1月12日在chrome中使用演示jsfiddle, switch-immediate是最快的解决方案。
结果: 时间分辨率:1.33
25ms "if-immediate" 150878146
29ms "if-indirect" 150878146
24ms "switch-immediate" 150878146
128ms "switch-range" 150878146
45ms "switch-range2" 150878146
47ms "switch-indirect-array" 150878146
43ms "array-linear-switch" 150878146
72ms "array-binary-switch" 150878146
完成了
1.04 ( 25ms) if-immediate
1.21 ( 29ms) if-indirect
1.00 ( 24ms) switch-immediate
5.33 ( 128ms) switch-range
1.88 ( 45ms) switch-range2
1.96 ( 47ms) switch-indirect-array
1.79 ( 43ms) array-linear-switch
3.00 ( 72ms) array-binary-switch
其他回答
你到底在//做什么?
你可以这样做:
(scrollLeft < 1000) ? //do stuff
: (scrollLeft > 1000 && scrollLeft < 2000) ? //do stuff
: (scrollLeft > 2000) ? //do stuff
: //etc.
当我查看其他答案中的解决方案时,我看到了一些我知道对性能不利的东西。我打算把它们放在评论中,但我认为最好是基准测试并分享结果。你可以自己测试。下面是我的结果(ymmv)在每个浏览器中最快的操作后归一化。
以下是2021年5月-05日的结果
Test | Chrome | Firefox | Opera | Edge | Brave | Node |
---|---|---|---|---|---|---|
1.0 time | 15 ms | 14 ms | 17 ms | 17 ms | 16 ms | 14 ms |
if-immediate | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 |
if-indirect | 2.20 | 1.21 | 2.06 | 2.18 | 2.19 | 1.93 |
switch-immediate | 2.07 | 1.43 | 1.71 | 1.71 | 2.19 | 1.93 |
switch-range | 3.60 | 2.00 | 2.47 | 2.65 | 2.88 | 2.86 |
switch-range2 | 2.07 | 1.36 | 1.82 | 1.71 | 1.94 | 1.79 |
switch-indirect-array | 2.93 | 1.57 | 2.53 | 2.47 | 2.75 | 2.50 |
array-linear-switch | 2.73 | 3.29 | 2.12 | 2.12 | 2.38 | 2.50 |
array-binary-switch | 5.80 | 6.07 | 5.24 | 5.24 | 5.44 | 5.37 |
2021年的测试在Windows 10 64bit上进行,版本如下:Chrome 90.0.4430.212, Firefox 80.9 b13, Opera 76.0.4017.123, Edge 90.0.818.62, Brave 1.24.85和Node 16.1.0(在WSL下运行)
苹果没有针对Windows更新Safari,所以它仍然是5.1.7版本。我在这次测试中把它改成了Brave。
以下是2012年9月至2004年的结果,用于历史比较:
Test | Chrome | Firefox | Opera | MSIE | Safari | Node |
---|---|---|---|---|---|---|
1.0 time | 37 ms | 73 ms | 68 ms | 184 ms | 73 ms | 21 ms |
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 |
2012年的测试在Windows 7 32位上进行,版本如下: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上的计时器分辨率是10ms而不是1ms。
眼前的
这是所有测试环境中最快的方法,除了……击鼓MSIE !(震惊)。
这是推荐的实现方法。
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%)。2021年Chrome浏览器使用时间(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
switch-immediate
当您可以通过计算来获得索引时,这种方法是有效的。
在2021年,它比if-immediate慢了40-120%(2012年:0-180%),除了在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;
}
switch-range2
这是switch-range的变体,但每个情况只有一个比较,因此更快。 case语句的顺序很重要,因为引擎将按照源代码顺序ECMAScript 2020 13.12.9测试每个case
在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;
}
switch-indirect-array
在这个变体中,范围存储在一个数组中。
在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;
}
array-linear-search
在这个变体中,范围存储在一个数组中。
在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-binary-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,并带有立即值。
您可以使用标准和与标准对应的函数创建一个自定义对象
var rules = [{ lowerLimit: 0, upperLimit: 1000, action: function1 },
{ lowerLimit: 1000, upperLimit: 2000, action: function2 },
{ lowerLimit: 2000, upperLimit: 3000, action: function3 }];
在这些情况下定义函数(定义function1, function2等)
并“评估”规则
function applyRules(scrollLeft)
{
for(var i=0; i>rules.length; i++)
{
var oneRule = rules[i];
if(scrollLeft > oneRule.lowerLimit && scrollLeft < oneRule.upperLimit)
{
oneRule.action();
}
}
}
Note
我讨厌使用30个if语句
很多时候,if语句更容易阅读和维护。 只有当你具备了很多条件,并且在未来有很大增长的可能性时,我才会推荐上面的建议。
更新 正如@Brad在评论中指出的那样,如果条件是互斥的(一次只能有一个条件为真),检查上限就足够了:
if(scrollLeft < oneRule.upperLimit)
假设条件按升序定义(首先是最低的,例如0到1000,然后是1000到2000)
这是另一种选择:
switch (true) {
case (value > 100):
//do stuff
break;
case (value <= 100)&&(value > 75):
//do stuff
break;
case (value < 50):
//do stuff
break;
}
更新已接受的答案(还不能评论)。截至2016年1月12日在chrome中使用演示jsfiddle, switch-immediate是最快的解决方案。
结果: 时间分辨率:1.33
25ms "if-immediate" 150878146
29ms "if-indirect" 150878146
24ms "switch-immediate" 150878146
128ms "switch-range" 150878146
45ms "switch-range2" 150878146
47ms "switch-indirect-array" 150878146
43ms "array-linear-switch" 150878146
72ms "array-binary-switch" 150878146
完成了
1.04 ( 25ms) if-immediate
1.21 ( 29ms) if-indirect
1.00 ( 24ms) switch-immediate
5.33 ( 128ms) switch-range
1.88 ( 45ms) switch-range2
1.96 ( 47ms) switch-indirect-array
1.79 ( 43ms) array-linear-switch
3.00 ( 72ms) array-binary-switch