所以我想使用这样的开关语句:
switch (scrollLeft) {
case (<1000):
//do stuff
break;
case (>1000 && <2000):
//do stuff
break;
}
现在我知道这些陈述中的任何一个(<1000
)或(>1000 && <2000
)都不起作用(显然有不同的原因)。我要问的是最有效的方法。我讨厌使用30个if
语句,所以我宁愿使用switch语法。有什么我可以做的吗?
答案 0 :(得分:619)
当我在其他答案中查看解决方案时,我看到一些我知道对性能有害的事情。我打算将它们放在评论中,但我认为最好对它进行基准测试并分享结果。你可以test it yourself。下面是我的结果(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
使用以下版本测试在Windows 7 32位上执行的操作: Chrome 21.0.1180.89m , Firefox 15.0 , Opera 12.02 , MSIE 9.0.8112 , Safari 5.1.7 。 节点在Linux 64位盒子上运行,因为Node.js for Windows上的计时器分辨率是10ms而不是1ms。
这是所有测试环境中最快的,除了...... drumroll MSIE! (惊讶,惊讶)。这是实施它的推荐方法。
if (val < 1000) { /*do something */ } else
if (val < 2000) { /*do something */ } else
...
if (val < 30000) { /*do something */ } else
这是switch-indirect-array
的变体,但有if
- 语句,而且在几乎所有测试环境中的执行速度都比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
这在所有测试环境中都非常快,实际上是MSIE中最快的。 它可以在您进行计算以获取索引时起作用。
switch (Math.floor(val/1000)) {
case 0: /* do something */ break;
case 1: /* do something */ break;
...
case 29: /* do something */ break;
}
这比所有测试环境中最快的慢6到40倍,除了 对于Opera而言需要大约一倍半的时间。它很慢,因为发动机 每个案例必须比较两次值。令人惊讶的是,与Chrome中最快的操作相比,Chrome完成此操作所需的时间要长近40倍,而MSIE只需要6倍的时间。但实际时差仅为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-range
的变体,但每个案例只有一个比较因此更快,但除了Opera之外仍然非常慢。 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;
}
在此变体中,范围存储在数组中。这在所有测试环境中都很慢,在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;
}
这是对数组中值的线性搜索和开关的组合 具有固定值的声明。人们可能想要使用它的原因是 值直到运行时才知道。它在每个测试环境中都很慢,在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-linear-switch
的变体,但带有二分搜索。
不幸的是它比线性搜索慢。我不知道这是我的实现还是线性搜索更优化。它也可能是键空间很小。
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
即时值。
答案 1 :(得分:85)
替代方案:
var scrollleft = 1000;
switch (true)
{
case (scrollleft > 1000):
alert('gt');
break;
case (scrollleft <= 1000):
alert('lt');
break;
}
答案 2 :(得分:20)
switch (Math.floor(scrollLeft/1000)) {
case 0: // (<1000)
//do stuff
break;
case 1: // (>=1000 && <2000)
//do stuff;
break;
}
只有在您有常规步骤时才有效...
编辑:由于这个解决方案不断提升,我必须建议mofolo's solution更好一点答案 3 :(得分:6)
您可以使用与条件
对应的条件和功能创建自定义对象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();
}
}
}
注意强> 的
我讨厌使用30条if语句
很多时候,语句更容易阅读和维护。 只有当你有很多条件和将来可能很多增长时,我才会推荐上述内容。
的更新强>
正如@Brad在评论中指出的那样,如果条件是互斥的(一次只能有一个条件是真的),检查上限就足够了:
if(scrollLeft < oneRule.upperLimit)
提供条件按升序排列(例如,首先是最低的,0 to 1000
,然后是1000 to 2000
答案 4 :(得分:3)
你到底在//do stuff
做了什么?
您可能会执行以下操作:
(scrollLeft < 1000) ? //do stuff
: (scrollLeft > 1000 && scrollLeft < 2000) ? //do stuff
: (scrollLeft > 2000) ? //do stuff
: //etc.
答案 5 :(得分:3)
未经测试且不确定这是否有效,但为什么不在之前执行一些if statements
来设置switch statement
的变量。
var small, big;
if(scrollLeft < 1000){
//add some token to the page
//call it small
}
switch (//reference token/) {
case (small):
//do stuff
break;
case (big):
//do stuff;
break;
}
答案 6 :(得分:1)
这是另一种选择:
switch (true) {
case (value > 100):
//do stuff
break;
case (value <= 100)&&(value > 75):
//do stuff
break;
case (value < 50):
//do stuff
break;
}
答案 7 :(得分:1)
更新已接受的答案(暂无法评论)。从2016年1月12日开始使用chrome中的demo 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
答案 8 :(得分:1)
在我的情况下(颜色编码百分比,没有任何性能关键),我很快写了这个:
function findColor(progress) {
const thresholds = [30, 60];
const colors = ["#90B451", "#F9A92F", "#90B451"];
return colors.find((col, index) => {
return index >= thresholds.length || progress < thresholds[index];
});
}
答案 9 :(得分:1)
我讨厌使用30条if语句
我最近遇到了同样的情况,这是我如何解决的:
<强>之前:强>
if(wind_speed >= 18) {
scale = 5;
} else if(wind_speed >= 12) {
scale = 4;
} else if(wind_speed >= 9) {
scale = 3;
} else if(wind_speed >= 6) {
scale = 2;
} else if(wind_speed >= 4) {
scale = 1;
}
<强>后:强>
var scales = [[4, 1], [6, 2], [9, 3], [12, 4], [18, 5]];
scales.forEach(function(el){if(wind_speed > el[0]) scale = el[1]});
如果你设置&#34; 1,2,3,4,5&#34;然后它可以更简单:
var scales = [4, 6, 9, 12, 18];
scales.forEach(function(el){if(wind_speed >= el) scale++});