在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
错误 ,所以当我们想要提高可读性的时候 ,让我们多一点创意。
所以我们不是评估每个case
是true
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; .... }
{期望对糟糕的代码的评论}
在上面的例子中,编译器没有实际的方法来进行静态优化,因此如果没有其他的话,就没有性能优势。
唯一的部分是,它可能“看起来更清洁的开发商,但可能会在附加条件的情况下有效的中断。