javascript: использование условия в случае переключения


88

Простите за глупый вопрос. Как я могу использовать условие для случая в элементе языка javascript switch-case? Как и в примере ниже, регистр должен совпадать, если переменная liCount<= 5 и> 0; однако мой код не работает:

switch (liCount) {
    case 0:
        setLayoutState('start');
        var api = $('#UploadList').data('jsp');
        api.reinitialise();
        break;
    case (liCount<=5 && liCount>0):
        setLayoutState('upload1Row');
        var api = $('#UploadList').data('jsp');
        api.reinitialise();
        break;
    case (liCount<=10 && liCount>5):
        setLayoutState('upload2Rows');
        var api = $('#UploadList').data('jsp');
        api.reinitialise();
        break;
    case (liCount>10):
        var api = $('#UploadList').data('jsp');
        api.reinitialise();
        break;                  
}

Спасибо за любой совет!


4
вместо этого используйте операторы if, если вы хотите это сделать ..
Нафтали, он же Нил,

3
Вы не должны игнорировать всех, кто говорит вам использовать ifs, потому что они правы. Это ужасное приложение switch.
Lincolnk

Я не могу поверить, что это решение не было предоставлено. Вы можете это сделать, просто нужно, чтобы оператор оценил значение в предложении switch. Так что это сработает:var liCount = 2; switch (liCount) { case 0: console.log(0); break; case (liCount<=5 && liCount>0) && liCount: console.log('liCount<=5 && liCount>0'); break; case (liCount<=10 && liCount>5) && liCount: console.log('liCount<=10 && liCount>5'); break; case (liCount>10) && liCount: console.log(liCount); break; }
Noitidart

Ответы:


286

Это работает:

switch (true) {
    case liCount == 0:
        setLayoutState('start');
        var api = $('#UploadList').data('jsp');
        api.reinitialise();
        break;
    case liCount<=5 && liCount>0:
        setLayoutState('upload1Row');
        var api = $('#UploadList').data('jsp');
        api.reinitialise();
        break;
    case liCount<=10 && liCount>5:
        setLayoutState('upload2Rows');
        var api = $('#UploadList').data('jsp');
        api.reinitialise();
        break;
    case liCount>10:
        var api = $('#UploadList').data('jsp');
        api.reinitialise();
        break;                  
}

В предыдущей версии этого ответа причиной были круглые скобки. По правде говоря, круглые скобки здесь не имеют значения - единственное, что необходимо, это switch(true){...}чтобы ваши выражения case оценивали логические значения.

Это работает, потому что значение, которое мы даем переключателю, используется в качестве основы для сравнения. Следовательно, выражения case, также вычисляющие логические значения, будут определять, какой case запускается. Можно также изменить это, передать switch(false){..}и получить желаемые выражения, оцениваемые как ложные, а не как истинные ... но лично предпочитаю иметь дело с условиями, которые оцениваются как истинность. Однако он тоже работает, поэтому стоит помнить о том, что он делает.

Например: если liCount равно 3, первое сравнение будет true === (liCount == 0), что означает, что первый случай неверен. Затем переключатель переходит к следующему случаю true === (liCount<=5 && liCount>0). Это выражение принимает значение true, что означает, что этот случай запускается и завершается на break. Я добавил здесь круглые скобки, чтобы было понятнее, но они необязательны, в зависимости от сложности вашего выражения.

Это довольно простой и изящный способ (если он соответствует тому, что вы пытаетесь сделать) обработки длинной серии условий, где, возможно, длинная серия ìf() ... else if() ... else if () ...может внести много визуального шума или хрупкости.

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


9
Думаю, тебе нужно switch(true) {, case liCount == 0:да? Иначе это сравнение есть liCount == (liCount <=5 && liCount > 0).
loganfsmyth

33
Вы знаете, это не потому, что вы можете, что вы должны . Это то, что нужно убить огнем.
JBert

21
Это часть языка - следовательно, лучше знать об этом, чем не знать. Ясно, что это не будет подходить для каждой ситуации, но на чисто субъективном уровне я думаю, что это интересный подход, и в данном случае он более четкий / менее хрупкий, чем серия ifs / elifs. Важно помнить, что кодирование - это выражение намерения в сочетании со вкусом и практикой. Наличие большего количества возможностей для четкого выражения себя в коде никогда не бывает плохим.
dmp

1
Для меня это был очень полезный и очень хороший способ организовать мою логику, где мне нужно было снова и снова использовать имя переменной на основе условия if, но это был сценарий типа n + 1, поэтому тот факт, что случай оператора switch без перерыв переместится на следующую строку ниже было критически полезно.
Джозеф Астрахан

2
Вы даже открыли нам глаза, чтобы увидеть, каков был бы результат, если бы выражение switch было таким ложным switch(false) { }
bello hargbola

24

Ты путь усложненной что. Напишите это с операторами if вместо этого:

if(liCount == 0)
    setLayoutState('start');
else if(liCount<=5)
    setLayoutState('upload1Row');
else if(liCount<=10)
    setLayoutState('upload2Rows');

$('#UploadList').data('jsp').reinitialise();

Или, если ChaosPandion пытается максимально оптимизировать:

setLayoutState(liCount == 0 ? 'start' :
               liCount <= 5 ? 'upload1Row' :
               liCount <= 10 ? 'upload2Rows' :
               null);

$('#UploadList').data('jsp').reinitialise();

Тебе нужно было пойти и одолеть меня. :)
ChaosPandion

Мы писали наши сообщения одновременно. Я не видел твоего, пока не опубликовал. Кажется, вы сейчас переусердствуете ...
Эрик

Вау, я действительно не думал о слишком сложных условных предложениях.
ChaosPandion

1
@Chaos: да, наверное, переборщил. Вам также придется добавить нулевую проверку setLayoutState: P.
Эрик

@Eric - некоторые программисты с большим количеством кругов программирования за плечами, чем я сказал: «только потому, что вы можете писать Javascript без фигурных скобок (и - на самом деле осторожно - с точкой с запятой), это не значит, что вы должны», но я просто переписал несколько В любом случае операторы if, как в вашем примере, так что спасибо - отлично работает, пока после условия не будет выполняться более одной строки. Однако тройное решение оказалось для меня слишком далеким мостом…
Дэйв Эверитт

7

Вы хотите использовать операторы if:

if (liCount === 0) {
    setLayoutState('start');
} else if (liCount <= 5) {
    setLayoutState('upload1Row');
} else if (liCount <= 10) {
    setLayoutState('upload2Rows');
}
$('#UploadList').data('jsp').reinitialise();  

7

См . Ответ dmp ниже. Я бы удалил этот ответ, если бы мог, но он был принят, так что это следующий лучший вариант :)

Вы не можете. Интерпретаторы JS требуют от вас сравнения с оператором switch (например, нет оператора case when). Если вы действительно хотите это сделать, вы можете просто делать if(){ .. } else if(){ .. }блоки.


9
Это неверно. Вот демонстрация, показывающая, как это работает: jsfiddle.net/Ender/fr3wL . Стандарт ECMAScript прямо заявляет, что это разрешено: docstore.mik.ua/orelly/webprog/jscript/ch06_05.htm#FOOTNOTE-18
Ender

3
@Ender Как это то же самое, что пытается сделать Хэмсе?
Aistina

@ Аистина Это не так. Поскольку его условия кейса производят истинное / ложное значение, а не числовое значение, haemse нужно было бы проверить свои кейсы на истинное значение (например, предложенное в ответе danp), а не сравнивать с числовым значением liCount. Я просто указал на то, что исходное утверждение cwolves о том, что «интерпретаторы JS требуют, чтобы операторы case были статическими значениями», было неверным. cwolves с тех пор изменил это утверждение, поэтому мой комментарий больше не актуален.
Эндер

Потому что это не отвечает на вопрос. Он не просил другого способа сделать это, он просил, чтобы шкаф работал так, как он хочет. «Сделай как-нибудь по-другому» почти никогда не бывает правильным ответом, хотя мы почти всегда так думаем. Мы всегда думаем, что у нас есть лучший способ, но он не хочет этого делать, делая этот ответ просто неправильным.
Jasmine

@Jasmine - «Ты не можешь, так сделай как-нибудь по-другому» - совершенно верно, если это правильно . Мой ответ отвергается, потому что это просто неправильно :) Как отметил @danp, вы можете просто переключиться, trueи это сработает . Но ему больше трех лет, так что мне все равно.
Марк Кан

5
switch (true) {
  case condition0:
    ...
    break;
  case condition1:
    ...
    break;
}

будет работать в JavaScript, пока ваши условия возвращают правильные booleanзначения, но у него нет особых преимуществ перед else ifоператорами.


Будет ли это работать, если я передам какое-нибудь целое число 10в операторе switch? в моем случае не работает, не знаю, в чем причина.
Pardeep Jain

10 !== true, так что нет. Есть ли какая-нибудь переменная, которая может иметь значение 10? Если x, то case x === 10:сработает.
Майк Сэмюэл

Но он должен работать так же, как и другие операторы, например, если вы используете if (10) {..}поток, он должен проходить в Ifусловии, не так ли? потому что 10 или любое целое число, кроме 0, будет рассматриваться как истинное значение и позволит войти в условие. Не уверен, что не так с его оператором переключения здесь.
Pardeep Jain,

1
@PardeepJain, switchпросто не работает if. ifпроверяет, является ли условие истинным . switchпроверяет , является ли выражение после того , switchявляется ===( CaseClauseIsSelected шаг 4 ) к значению выражения после case.
Майк Сэмюэл

Ох, как это, спасибо. Для меня это было совершенно внове. @Mike
Pardeep Jain

4

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


4

Если это то, что вы хотите сделать, лучше использовать ifоператоры. Например:

if(liCount == 0){
    setLayoutState('start');
}
if(liCount<=5 && liCount>0){
    setLayoutState('upload1Row');
}
if(liCount<=10 && liCount>5){
    setLayoutState('upload2Rows');
}             
var api = $('#UploadList').data('jsp');
    api.reinitialise();

2

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

Так, например, скажем liCount = 2. Ваш первый случай не подходит, потому что 2 != 0. Ваш второй случай (liCount<=5 && liCount>0)оценивается как true, но2 != true , поэтому и этот случай не будет соответствовать.

По этой причине, как говорили многие другие, для этого вам следует использовать серию if...then...else ifблоков.


2

если возможные значения являются целыми числами, вы можете группировать случаи. В противном случае используйте ifs.

var api, tem;

switch(liCount){
    case 0:
    tem= 'start';
    break;
    case 1: case 2: case 3: case 4: case 5:
    tem= 'upload1Row';
    break;
    case 6: case 7: case 8: case 9: case 10:
    tem= 'upload2Rows';
    break;
    default:
    break;
}
if(tem) setLayoutState((tem);
api= $('#UploadList').data('jsp');
api.reinitialise();

0

Обратите внимание, что мы не передаем счет переключателю, но это правда. Значение, которое мы даем переключателю, используется в качестве основы для сравнения.

В приведенном ниже примере показано, как мы можем добавлять условия в случае: без каких-либо операторов if.

function getGrade(score) {
    let grade;
    // Write your code here
    switch(true) {
        case score >= 0 && score <= 5:
        grade = 'F';
        break;
        case score > 5 && score <= 10:
        grade = 'E';
        break;
        case score > 10 && score <= 15:
        grade = 'D';
        break;
        case score > 15 && score <= 20:
        grade = 'C';
        break;
        case score > 20 && score <= 25:
        grade = 'B';
        break;
        case score > 25 && score <= 30:
        grade = 'A';
        break;
    }

    return grade;
}

0

Хотя в конкретном примере вопроса OP switchэто не подходит, есть пример, где переключатель все еще уместен / полезен, но также требуются другие выражения оценки. Этого можно добиться, используя для выражений предложение по умолчанию:

switch (foo) {
  case 'bar':
    // do something
    break;
  case 'foo':
    // do something
    break;
  ... // other plain comparison cases
  default:
    if (foo.length > 16) {
      // something specific
    } else if (foo.length < 2) {
      // maybe error
    } else {
      // default action for everything else
    }
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.