Выражение внутри оператора case переключателя - PullRequest
31 голосов
/ 12 августа 2010

Я пытаюсь создать оператор 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;
    }
}

Я что-то упускаю из виду или этоневозможно?Google не был дружественным в этом случае.

Любая помощь / указатели оценили

M

Ответы [ 8 ]

101 голосов
/ 12 августа 2010

Вы всегда можете сделать

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

  //etc...

Это работает, потому что true является константой, поэтому будет выполнен код в первом операторе case с выражением, которое оценивается как true.

Это довольно "сложно", я думаю, но я не вижу ничего плохого в его использовании.Простое if/else утверждение, вероятно, будет более кратким, и вам не придется беспокоиться о случайном провале.Но там все равно.

11 голосов
/ 15 февраля 2013

@ MooGoo's switch (true) даст вам ошибку Weird condition в jsLint , поэтому давайте немного креативнее в случае возникновения проблемы и, думаю, увеличимудобочитаемость одним касанием.

Таким образом, мы не оцениваем, является ли каждый case true или false;мы сравниваем, если это значение case равно нашему switch члену.Итак, давайте воспользуемся этим, добавив сокращение if в наш оператор case и вернем наш первоначальный термин switch, если условие истинно .

Я также включаю в себя своего родапример реального мира, где вы хотите иметь два «значения по умолчанию» - одно, если ваш термин находится за пределами вашего «важного» диапазона в положительном направлении, и другое, если вы находитесь в отрицательном направлении.

Ключевая фраза: case (x > 0 ? x : null):

"Если мой термин x больше нуля, верните x, чтобы x === x и я выбрал ветвь кейса."

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.');
10 голосов
/ 12 августа 2010

Это не то, как работает блок switch.case используется для хранения одного значения, если оно равно значению в строке switch.if-else заявления будут вам полезны.

Вот некоторая информация о блоке switch.

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

3 голосов
/ 12 августа 2010

Во-первых, это не так, как switch работает.Вы должны указать константы для каждого case, и эти константы будут сравниваться с выражением в скобках (в вашем случае, amount).Вот как работает switch, точка.

Во-вторых, коммутатор не быстрее, чем несколько if с

И, в-третьих, вам не следует беспокоиться о минимальной оптимизации производительности, когда вы 'имеем дело с JavaScript.

1 голос
/ 13 декабря 2015

Ну, вы можете иметь выражения в выражении case, поэтому ваш переключатель не является синтаксической ошибкой.Но вы должны понимать, что 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 является выражением для оценки.То же самое, что и вы, только вы не вернули значение, равное сумме, но верное или ложное значение.В моем примере я возвращаю точную сумму, если мое условие истинно, поэтому запускаю сравнение, чтобы соответствовать.

Вот ваш фиксированный код:

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, потому что ее проще искать, чем старый pdf es3 1999 года. Но он всегда работал так, но это малоизвестный факт.

Однако я сомневаюсь, что это быстреечем if заявления.Если вы хотите, чтобы ваш пробег был быстрым, то не не трогайте DOM.

1 голос
/ 19 февраля 2014

Вы также можете попробовать одну из моих любимых конструкций:

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"
    );
}
1 голос
/ 02 ноября 2011

Проблема в том, что выражение переключателя никогда не может быть равно выражениям регистра, потому что выражение регистра будет иметь значение true или false, но выражение переключения будет числом.

Решение, в котором установлено выражение переключенияк истине работает не потому, что истина является константой, а потому, что равенство с падежными выражениями действительно возможно.

Это неправда, что вы должны указывать константы для каждого выражения case.

Чтобы подтвердить мой ответ, обратитесь к Дугласу Крокфорду, Javascript The Good Parts (2008), стр. 12:

Оператор switch выполняет многопотоковую ветвь.Он сравнивает выражение на равенство со всеми выбранными случаями .... Когда найдено точное совпадение, выполняются операторы соответствующего предложения case ... Предложение case содержит одно или несколько выражений case.Выражения регистра не обязательно должны быть константами.

0 голосов
/ 29 октября 2015

Мои 2 цента:

В идеале switch (как правило) должен оценивать одну ветвь падежа, тем самым достигая производительности O (1) и (кроме падений падежа) операторы case можно переупорядочить любым способом без изменения стратегии ветвления компилятора. 1003 *

Если используются выражения (при условии, что это позволяет язык), то теоретически оно может следовать больше, чем ветвь.

Компилятор (кроме тех, которые могут разумно сказать, что пытается сделать разработчик) не сможет оптимизировать стратегию ветвления статически и в идеале, что приведет к потере его эффективности.

Пример:

var x = 6, factors = [];

switch(x){

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

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

{Ожидайте комментариев о плохом коде}

В вышеприведенном примере компилятор не имеет практического способа статической оптимизации, поэтому не получает никакого выигрыша в производительности по сравнению с другими.

Единственная часть заключается в том, что он «может» выглядеть более чистым для разработчика, но в действительности может стать причиной сбоев в случае возникновения дополнительных условий.

...