在switch case语句中的expression式

我试图创build一个switch语句,但我似乎无法使用得到评估的expression式(而不是一个string/整数)。 我可以很容易地做到这一点,如果发言,但情况应该希望更快。

我正在尝试以下

function reward(amount) { var $reward = $("#reward"); switch (amount) { case (amount >= 7500 && amount < 10000): $reward.text("Play Station 3"); break; case (amount >= 10000 && amount < 15000): $reward.text("XBOX 360"); break; case (amount >= 15000): $reward.text("iMac"); break; default: $reward.text("No reward"); break; } } 

我错过了一些明显的东西,或者这是不可能的? Google在这种情况下并不友善。

任何帮助/指针赞赏

中号

你可以随时做

 switch (true) { case (amount >= 7500 && amount < 10000): //code break; case (amount >= 10000 && amount < 15000): //code break; //etc... 

它的工作原理是因为true是一个常量,所以第一个case语句下的代码的计算结果为true将被执行。

我想这有点儿“棘手”,但是我没有看到使用它的任何错误。 一个简单的if/else语句可能会更加简洁,而且不必担心意外丢失。 但无论如何。

这不是一个switch块的工作方式。 这种case是用来保存一个单一的值,如果他们等于switch线上的值。 if-else语句将很好地为您服务。

这是关于switch块的一些信息。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/switch

@ MooGoo的switch (true) 在jsLint中会给你一个Weird condition错误 ,所以当我们想要提高可读性的时候 ,让我们多一点创意。

所以我们不是评估每个casetrue false ; 我们正在比较这个case的价值是否等于我们的switch期限。 所以,让我们利用这一点, if在我们的case陈述中抛出速记if返回我们原来的开关期限,如果条件成立的话

我还包括一个真实世界的例子,你想要有两个“默认值” – 一个是如果你的术语在正面方向上超出“重要”范围,另一个是负面方向。

关键短语: case (x > 0 ? x : null):

“如果我的术语x大于零,则返回x以使x === x和I取分支。”

http://jsfiddle.net/rufwork/upGH6/1/

 /*global document*/ /*jslint evil:true*/ var x = 10; switch (x) { case (x > 0 ? x : null): document.write('ha ha ha! I fooled switch AND jsLint! Muhahahahaha!'); break; case 0: document.write('zero is nothing.'); break; case -1: document.write('low'); break; case -2: document.write('lower'); break; case -3: document.write('lowest I care about'); break; default: // anything lower than -3. document.write('TOO LOW!!!! (unless you cheated and didn\'t use an int)'); } document.write('<br>done.'); 

首先,这不是如何switch作品。 你必须为每个case指定常量,并将这些常量与括号中的expression式(在你的情况下, amount )进行比较。 这就是switch如何工作的时期。

其次,开关不会比几个s快

第三,当你处理javascript时,你不应该担心微小的性能优化。

问题是开关expression式不能等于caseexpression式,因为caseexpression式将计算为true或false,但开关expression式将是一个数字。

开关expression式设置为true的解决scheme不是因为true是常量,而是因为与caseexpression式的相等实际上是可能的。

你不得不为每个caseexpression式指定常量。

要备份我的答案,请参阅Douglas Crockford,Javascript The Good Parts(2008),第12页:

switch语句执行多路分支。 它比较与所有选定案例相等的expression式….当find完全匹配时,匹配case子句的语句被执行… case子句包含一个或多个caseexpression式。 caseexpression式不一定是常量。

你也可以尝试我最喜欢的build筑之一:

 function reward(amount) { var $reward = $("#reward"); $reward.text( (amount >= 7500 && amount < 10000) ? "Play Station 3" : (amount >= 10000 && amount < 15000)? "XBOX 360" : (amount >= 15000) ? "iMac" : "No reward" ); } 

那么,你可以在case语句中有expression式,这就是为什么你的开关不是语法错误。 但是你必须明白,使用===(严格比较)比较案例子句 。 一旦你明白了这一点,这个值必须完全匹配你的switch(expression)的expression式值,你可以购买js中的expression式。

函数调用是expression式,所以让我们尝试一下:

 function xbox(amount) { return amount >= 10000 && amount < 15000 && amount; } function reward(amount) { var ps3 = function(amount) { return amount >= 7500 && amount < 10000 && amount; } function imac(amount) { return amount >= 15000 && amount; } var $reward = $("#reward"); switch (amount) { case ps3(amount): $reward.text("Play Station 3"); break; case xbox(amount): $reward.text("XBOX 360"); break; case imac(amount): $reward.text("iMac"); break; default: $reward.text("No reward"); break; } } reward(8200)// -> Play Station 3 reward(11000)// -> XBOX 360 reward(20000)// -> iMac 

正如你所看到的,你可以使用函数expression式和函数定义。 没关系。 只有case子句中的expression式才是一个expression式。 这与你所做的一样,只是你没有返回一个与金额相同的价值,而是一个真实或虚假的价值。 在我的例子中,如果我的条件是真的,我会返回确切的金额,从而触发比较匹配。

这里是你的固定代码:

 function reward(amount) { var $reward = $("#reward"); switch (amount) { case (amount >= 7500 && amount < 10000 && amount): $reward.text("Play Station 3"); break; case (amount >= 10000 && amount < 15000 && amount): $reward.text("XBOX 360"); break; case (amount >= 15000 && amount): $reward.text("iMac"); break; default: $reward.text("No reward"); break; } } 

这里是规范: https ://tc39.github.io/ecma262/#sec-switch-statement该链接是es2016,因为它比从1999年以前的es3 pdf更容易查找。但它一直这样工作,但这是一个鲜为人知的事实。

然而,我怀疑这比if语句要快。 如果你想运行得很快,那么不要碰DOM。

我的2美分:

理想情况下,切换(作为一个原则)应该评估到一个单一的案例分支,从而实现O(1)的性能和(除了通过案例以外)案例语句可以以任何方式重新sorting而无需改变编译器分支策略。

如果使用expression式(假设语言允许),那么在理论上,它可以比分支更多地遵循。

编译器(除了那些可以智能地说出开发人员正在做什么的)将不能够静态地优化分支策略,从而失去效果。

例:

 var x = 6, factors = []; switch(x){ case (x%2 == 0): factors.push(2); break; case (x%3 == 0): factors.push(3); break; .... } 

{期望对糟糕的代码的评论}

在上面的例子中,编译器没有实际的方法来进行静态优化,因此如果没有其他的话,就没有性能优势。

唯一的部分是,它可能“看起来更清洁的开发商,但可能会在附加条件的情况下有效的中断。