Подтвердить что ты не робот

Выражение внутри оператора case switch

Я пытаюсь создать оператор switch, но я не могу использовать выражение, которое получает оценку (а не набор string/integer). Я могу легко сделать это, если утверждения if, но случай, надеюсь, будет быстрее.

Я пытаюсь выполнить следующие

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

4b9b3361

Ответ 1

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

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

  //etc...

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

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

Ответ 2

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

Ниже приведена информация о блоке switch.

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

Ответ 3

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

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

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

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

"Если мой член x больше нуля, верните x, чтобы 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.');

Ответ 4

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

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

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

Ответ 5

Проблема заключается в том, что выражение 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 не обязательно должны быть константами.

Ответ 6

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

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

Ответ 7

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

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

Ответ 8

Мои 2 цента:

Идеальный переключатель (как принцип) должен оцениваться в одной ветки 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;
    ....
 }

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

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

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