switch case 语句中的表达式

IT技术 javascript switch-statement case
2021-01-22 04:10:24

我正在尝试创建一个 switch 语句,但我似乎无法使用被评估的表达式(而不是一组字符串/整数)。我可以使用 if 语句轻松地做到这一点,但 case 应该会更快。

我正在尝试以下

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;
    }
}

我错过了一些明显的东西还是这是不可能的?在这种情况下,谷歌并不友好。

任何帮助/指针表示赞赏

6个回答

你总能做到

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

  //etc...

它之所以有效,true因为它是一个常量,因此将执行第一个 case 语句下的代码,其表达式为真。

我想这有点“棘手”,但我认为使用它没有任何问题。一个简单的if/else语句可能会更简洁,您不必担心意外落空。但无论如何它就在那里。

是的,这是有效的,因为您总是可以将 switch 函数想象成一个跳转表,它只需要匹配和检索一个值。这与 if/else 语句不同,因为所有 if 都需要实际评估。在上面,您要求您的交换机评估 vs 匹配。这就是为什么 switch case 更快的原因。
2021-03-31 04:10:24
@Vontei - 使用 if/else if/else 结构,它们不会全部被评估,它们只会被依次评估,直到特定条件为真,这与评估case表达式发生的情况相同
2021-04-02 04:10:24
作为答案,这比丹尼尔斯的“答案”更好。有一个轻微的警告:导致 case true 的表达式之前的所有表达式也将被评估。当心。
2021-04-08 04:10:24

@MooGoo'sswitch (true)Weird condition在 jsLint 中给你一个错误,所以让我们多一点创意,以防万一这是一个问题,我认为,增加可读性。

所以我们不评估每个casetruefalse我们正在比较它case的值是否等于我们的switch术语。因此,让我们利用这一点,if在我们的case语句中加入一个速记,在条件为 true 时返回我们原来的 switch 项

我还包括了一种现实世界的例子,你想要有两个“默认值”——一个如果你的术语在积极的方向上超出你的“重要”范围,另一个如果你处于负面方向。

关键词: case (x > 0 ? x : null):

“如果我的术语 ,x大于零,则返回xx === x然后我采用 case 分支。”

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.');

快速回复@Sv443

请注意default:开关说,“除非你作弊并且没有使用 int ”,并且x === x当你返回时需要短路x

但你的观点是一个有用的提醒,这NaN短路不能适用唯一情况。

也就是说,x必须== x短路switch,正如 MDN 告诉我们的那样,“ NaN,并且只有 NaN,将与自身进行比较不相等”(doubletriple =)。

这也意味着在该切换NaN值(和唯一的一个NaN数值)将始终defaultANY switch,因为你无法比拟的value。

这是MDN的完整报价

NaN 将不相等(通过 ==、!=、=== 和 !==)与任何其他值进行比较——包括与另一个 NaN 值。使用 Number.isNaN() 或 isNaN() 最清楚地确定一个值是否为 NaN。或者执行自我比较:NaN,并且只有 NaN,将与自身不相等。

您可以更改default逻辑以检查您拥有的内容:

isNaN(x) ? document.write ('nan') : document.write('TOO LOW!!!! ...)');

或者你甚至可以像 MDN 建议的那样完全时髦(但请不要;^D):

x !== x ? document.write ('nan') : document.write('TOO LOW!!!! ...)');

请注意,这在 when 时不起作用x = NaN,因为在内部 JS 可能会进行相等性检查,这对于NaN常量是不可能的(它需要使用 进行检查Number.isNaN(),但它不这样做)
2021-03-14 04:10:24
@Sv443 在答案更新中解决。在这种情况下NaN,字面上是证明(嗯,是唯一的例外)规则的例外。
2021-03-15 04:10:24
这可能会愚弄 JSLint,但比 JSLint 最初抱怨的东西更奇怪、更难阅读。如果你有意识地决定switch在 OP 想要的情况下使用with 表达式并且 MooGoo 解释过,那么你就不会担心那个特定的 JSLint 警告。
2021-03-25 04:10:24
@nnnnnn 好吧,我想说的switch (true)是完全反模式,因为 MooGoo 本质上是在重新创建if... else if... else. 我的主要观点是,这个问题确实让我想到了 switch 范围的一个可以说是实际的用途——如果你发现自己处于一个switch本质上需要两个 (+?) defaults范式中很高兴了解到您可以在 a 中使用表达式case,返回您switch的 param 值,并在该语句中强制调用。但听起来你是在投票给 @Daniel 和 @FyodorSoikin 的“这不是 switch 的工作方式”的答案,我真的无法反驳;)
2021-03-25 04:10:24
感谢您编辑这个 8 岁的答案:)
2021-04-04 04:10:24

这不是switch块的工作方式。所述case用于保持一个单一的值,如果它们是相等的值switch线。if-else陈述会很好地为您服务。

这是有关该switch块的一些信息

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

这个答案仍然是错误的:检查规范 -无论⟨expr1⟩⟨expr2⟩switch( ⟨expr1⟩ ){ case ⟨expr2⟩ : break; }是表达式。
2021-03-22 04:10:24

好吧,您可以在case语句中使用表达式,这就是为什么您的 switch 不是语法错误的原因。但是您必须了解,Case 子句是使用 ===(严格比较)进行比较的。一旦你理解了这一点,该值必须与你的表达式值完全匹配,switch(expression)你可以在 js 中货比三家。

函数调用是表达式,所以让我们尝试使用它们:

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

如您所见,您既可以使用函数表达式,也可以使用函数定义。没关系。只是 case 子句中的表达式是要计算的表达式。这与您所做的相同,只是您没有返回与金额相同的值,而是返回真值或假值。在我的示例中,如果我的条件为真,我将返回确切的数量,从而触发比较以匹配。

这是您的固定代码:

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。

你也可以尝试我最喜欢的结构之一:

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"
    );
}
我想这当然会阻止获得更大奖励的人更快地获得奖励;)
2021-03-26 04:10:24
如果您反向评估它们,您是否仍然需要检查金额是否低于数字?
2021-03-27 04:10:24
嵌套的三元运算符经常被完全恐惧和阻止。因此最好避免使用它们,除非它们比替代结构更简单、明显且更易于维护。我更喜欢以任何顺序工作的测试。无论您选择如何编写它们,简单性和可维护性在这里都胜过效率。
2021-03-30 04:10:24