switch case 语句内的表达式

发布于 2025-01-15 21:28:29 字数 759 浏览 0 评论 0原文

我正在尝试创建一个 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;
    }
}

我是否遗漏了一些明显的东西或者这是不可能的?谷歌在这起案件中并不友好。

任何帮助/指示表示赞赏

M

I'm trying to create a switch statement but I can't seem to be able to use an expression that gets evaluated (rather than a set string/integer). I can easily do this with if statements but case should hopefully be faster.

I'm trying the following

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

Am i missing something obvious or is this not possible? Google hasn't been friendly in this case.

Any help/pointers appreciated

M

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

挽清梦 2025-01-22 21:28:29

amount 是一个数字,但 case 子句中的表达式仅计算为布尔值;这些值永远不会匹配。

你总是可以这样做

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

它有效,因为匹配的值现在是布尔值 true,因此第一个 case 子句下的代码具有计算结果为 true< 的表达式/code> 将被执行。

我想这有点“棘手”,但我认为使用它没有什么问题。一个简单的 ifelse 语句可能会更简洁,而且您不必担心意外失败。但无论如何它就在那里。

amount is a number, but the expressions in the case clauses only evaluate to booleans; the values will never match.

You could always do

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

It works because the value being matched is now the boolean true, so the code under the first case clause with an expression that evaluates to true will be executed.

It’s kinda “tricky”, I guess, but I see nothing wrong with using it. A simple ifelse statement would probably be more concise, and you’d not have to worry about accidental fall-through. But there it is anyway.

享受孤独 2025-01-22 21:28:29

@MooGoo 的 switch (true) 会给你一个 jsLint 中出现奇怪的情况错误,所以让我们更有创意一点,以防万一这是一个问题,而且我认为,可以增加一点可读性。

因此,我们不会评估每个 casetrue 还是 false;我们正在比较该 case 的值是否等于我们的 switch 项。因此,让我们利用这一点,在 case 语句中添加一个速记 if,并如果条件为 true,则返回原始 switch 项

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

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

“如果我的项 x 大于零,则返回 x 以便 < code>x === 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

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

但您的观点是一个有用的提醒,即 NaN 是短路无法应用的唯一情况。

也就是说,x 必须 == x 才能在 switch 中短路,并且正如 MDN 告诉我们的那样,“< a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN#examples" rel="noreferrer">NaN,并且只有 NaN,才会比较不相等到本身”(双三重=)。

这也意味着打开 NaN 值(并且 NaN 值)将始终命中 ANY switch 中的 default 因为您无法匹配它的值。

以下是 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('太低了!!!! ...)');

@MooGoo's switch (true) will give you a Weird condition error in jsLint, so let's get a little more creative in case that's an issue, and, I think, increase readability a touch.

So we're not evaluating if each case is true or false; we're comparing if that case's value is equal to our switch term. So let's take advantage of that by throwing a shorthand if into our case statement and return our original switch term if the condition's true.

I'm also including a sort of real world example, where you want to have two "defaults" -- one if your term is outside of your "important" range in the positive direction, and another in case you're in the negative direction.

Key phrase:
case (x > 0 ? x : null):

"If my term, x, is greater than zero, return x so that x === x and I take the case branch."

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

Quick reply to @Sv443:

Do notice that the default: switch says, "unless you cheated and didn't use an int" and that short circuiting requires x === x when you return x.

But your point is a useful reminder that NaN is the only case where short circuiting can't apply.

That is, x must == x to short circuit in switch and, as MDN tells us, "NaN, and only NaN, will compare unequal to itself" (double or triple =).

That also means that switching on a NaN value (and only a NaN value) will always hit default in ANY switch because you can't match its value.

Here's the full quote from MDN:

NaN compares unequal (via ==, !=, ===, and !==) to any other value -- including to another NaN value. Use Number.isNaN() or isNaN() to most clearly determine whether a value is NaN. Or perform a self-comparison: NaN, and only NaN, will compare unequal to itself.

You could change the default logic to check what you have:

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

Or you even could go full hipster like MDN suggests (but please don't ;^D):

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

月牙弯弯 2025-01-22 21:28:29

这不是 switch 块的工作原理。 case 用于保存单个值,如果它们等于 switch 行上的值。 if-else 语句会对您很有帮助。

以下是有关 switch 块的一些信息。

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

That is not how a switch block works. The case is used to hold a single value that if they are equal to the value on the switch line. if-else statements will serve you well.

Here is some information about the switch block.

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

御弟哥哥 2025-01-22 21:28:29

好吧,您可以在 case 语句中包含表达式,这就是为什么您的 switch 不是语法错误。但你必须明白Case Clause是使用===(严格比较)进行比较的。一旦理解了这一点,该值必须与 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 子句中的表达式是要计算的表达式。这与您所做的相同,只是您没有返回与金额相同的值,而是返回 true 或 false 值。在我的示例中,如果我的条件为真,我将返回确切的金额,从而触发比较以匹配。

这是您的固定代码:

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-语句
链接指向 es2016,因为它比 1999 年的旧 es3 pdf 更容易查找。但它一直都是这样工作的,但这是一个鲜为人知的事实。

然而,我怀疑这比 if 语句更快。如果您希望运行得更快,那么不要触摸 DOM。

Well, you can have expressions in case statement which is why your switch is not a syntax error. But you have to understand that the Case Clause is compared using === (strict comparison). Once you understand this, that the value must match exactly with the expression value in your switch(expression) you can shop around for expressions in js.

Function calls are expressions, so let's try with them:

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

As you can see, you can both use function expressions and function definitions. It doesn't matter. Only that the expression in the case clause is an expression to evaluate. Which is the same as you did, only you did not return a value that was the same as the amount but rather a true or false value. In my example I return the exact amount if my condition is true, hence trigger the comparison to match.

Here is your fixed code:

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

Here is the specification: https://tc39.github.io/ecma262/#sec-switch-statement
The link is to es2016 because it's easier to lookup than the old es3 pdf from 1999. But it has always worked like this, but it is a little known fact.

I however doubt that this is faster than if statements. If you want your run to run fast, then do not touch the DOM.

假面具 2025-01-22 21:28:29

您还可以尝试我最喜欢的结构之一:

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

You could also try one of my favorite constructions:

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"
    );
}
恏ㄋ傷疤忘ㄋ疼 2025-01-22 21:28:29

问题是 switch 表达式永远不能等于 case 表达式,因为 case 表达式的计算结果为 true 或 false,但 switch 表达式将是一个数字。

将 switch 表达式设置为 true 的解决方案之所以有效,不是因为 true 是常量,而是因为与 case 表达式相等实际上是可能的。

必须为每个 case 表达式指定常量是不正确的。

为了支持我的答案,请参阅 Douglas Crockford,Javascript The Good Parts (2008),第 12 页:

switch 语句执行多路分支。它将表达式与所有选定的 case 进行比较,看是否相等...当找到完全匹配时,将执行匹配的 case 子句的语句... case 子句包含一个或多个 case 表达式。 case 表达式不必是常量。

The problem is the switch expression cannot ever equal the case expressions, because the case expression will evaluate to true or false, but the switch expression will be a number.

The solution where the switch expression is set to true works not because true is a constant but because equality with the case expressions is actually possible.

It's not true that you have to specify constants for each case expression.

To back up my answer, refer to Douglas Crockford, Javascript The Good Parts (2008), page 12:

The switch statement performs a multiway branch. It compares the expression for equality with all the selected cases.... When an exact match is found, the statements of the matching case clause are executed... A case clause contains one or more case expressions. The case expressions need not be constants.

热情消退 2025-01-22 21:28:29

我的 2 美分:

理想情况下, switch (作为原则)应该评估为单个 case 分支,从而实现 O(1) 性能,并且(除了失败案例之外)case 语句可以以任何方式重新排序,而无需更改编译器分支策略。

如果使用表达式(假设语言允许),那么理论上,它可以遵循多个分支。

编译器(除了那些能够智能地说明开发人员正在尝试做什么的编译器之外)将无法静态且理想地优化分支策略,从而失去其有效性。

示例:

var x = 6, factors = [];

switch(x){

    case (x%2 == 0): factors.push(2);
    break;

    case (x%3 == 0): factors.push(3);
    break;
    ....
 }

{期望对不良代码的评论}

在上面的示例中,编译器没有实际的方法进行静态优化,因此与 if else 相比没有获得任何性能优势。

唯一的部分是,它“可能”对开发人员来说看起来更干净,但实际上可能会在出现其他条件时导致中断。

My 2 cents:

Ideally switch (as a principle) should evaluate to a single case branch , thereby achieving O(1) performance and (other than fall through cases) the case statements can be reordered in any way without changing the compiler branching strategy.

If expressions are used (assuming the language allows it), then theoretically, it can follow more than branch.

The compiler (other than those which can intelligently say what the developer is trying to do) will not be able to optimize the branching strategy statically and ideally thus losing its effectiveness.

Example:

var x = 6, factors = [];

switch(x){

    case (x%2 == 0): factors.push(2);
    break;

    case (x%3 == 0): factors.push(3);
    break;
    ....
 }

{Expect comments on poor code}

In the above example, there is no practical way for the compiler to statically optimize, thus gains no performance benefit over if else.

The only part is that, it "may" look cleaner to the developer but could in-effect be cause for disruption in case of additional conditions.

爱你不解释 2025-01-22 21:28:29

首先,这不是 switch 的工作原理。您必须为每个case指定常量,这些常量将与括号中的表达式进行比较(在您的情况下,amount)。这就是 switch 的工作原理。

其次,switch 并不比几个 if 快。

第三,在处理 javascript 时,您不应该真正担心微小的性能优化。

Firstly, that's not how switch works. You have to specify constants for each case, and those constants will be compared to the expression in parentheses (in your case, amount). That is how switch works, period.

Secondly, switch is not faster than several ifs

And thirdly, you shouldn't really worry about miniscule performance optimizations when you're dealing with javascript.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文