javascript: використання умови у випадку перемикача


88

Вибачте за це німе запитання. Як я можу використовувати умову для справи в елементі мови переключення регістрів javascript? Як у прикладі нижче, випадок повинен збігатися, коли змінна 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){...}і для виразів вашого випадку оцінити булеві значення.

Це працює, оскільки значення, яке ми надаємо комутатору, використовується як основа для порівняння. Отже, вирази регістру, які також обчислюють логічні значення, визначатимуть, який випадок буде запущено. Можна також перевернути це, і передати, switch(false){..}і бажані вирази оцінити як false, а не true .. але особисто волію мати справу з умовами, які оцінюють як істинність. Однак він теж працює, тому варто пам’ятати, щоб зрозуміти, що він робить.

Наприклад: якщо 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
Це частина мови - отже, знати про неї краще, ніж ні. Очевидно, що це не підходить для будь-якої ситуації, але на суто суб’єктивному рівні, я думаю, це цікавий підхід, який є більш розбірливим / менш крихким, ніж серія if / elifs у цьому випадку. Важливо пам’ятати, що кодування - це вираження намірів, поєднане зі смаком та практикою. Мати більше можливостей чітко виразитися в коді - це ніколи не погано.
dmp

1
Для мене це було дуже корисно і дуже приємний спосіб організувати свою логіку, де мені потрібно було використовувати ім'я змінної знову і знову на основі умови if, але це був сценарій типу n + 1, тому той факт, що випадок оператора перемикання без перерва на наступний рядок нижче була критично корисною.
Джозеф Астраган

2
Ви навіть відкрили нам очі, щоб побачити, яким був би результат, якби вираз перемикача був хибним так 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
Ендер,

3
@Ender Як це те саме, що те, що намагається зробити Хемс?
Aistina

@Aistina Це не так. Оскільки його умови справи дають істинне / хибне значення, а не числове значення, Хемсе потрібно було б перевірити свої випадки на істинне значення (наприклад, запропоноване у відповіді Данпа), а не тестувати на основі числового значення liCount. Я просто вказував, що оригінальне твердження cwolves про те, що "JS Interpreters вимагають, щоб оператори регістру були статичними значеннями", було неправильним. cwolves з тих пір переглянув це твердження, тому мій коментар більше не актуальний.
Ендер,

Тому що це не відповідає на питання. Він не просив про інший спосіб зробити це, він попросив зробити так, щоб коробка перемикачів працювала так, як він хоче. "Зроби це по-іншому" майже ніколи не є правильною відповіддю, незважаючи на те, що ми майже завжди думаємо, що це так. Ми завжди думаємо, що маємо кращий спосіб, але він не так хоче зробити, роблячи цю відповідь просто неправильною.
Жасмин

@Jasmine - "Ви не можете, тому робіть це по-іншому" цілком дійсне, якщо це правильно . За мою відповідь голосують проти, тому що це просто неправильно :) Як зазначив @danp, ви можете просто перейти проти, trueі це працює. Але йому вже понад 3 роки, тому мені насправді все одно.
Mark Kahn

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

працюватиме в JavaScript до тих пір, поки ваші умови повернуть належні booleanзначення, але він не має великих переваг перед else ifоператорами.


Чи спрацює це, якщо я передаю деяке ціле число 10в операторі switch? в моєму випадку не працює, не знаю, в чому причина.
Пардіп Джайн

10 !== true, так що ні. Чи існує якась змінна, яка може мати значення 10? Якщо x, тоді case x === 10:б спрацювало.
Майк Семюел

Але це повинно працювати як інші твердження, наприклад, якщо ви використовуєте if (10) {..}потік, який повинен передаватися в Ifумові, чи не так? оскільки 10 або будь-яке ціле число, крім 0, буде розглядатися як достовірне значення і дозволить ввести в умову. Не впевнений, що поганого в тому, що він перемикає оператор тут.
Пардіп Джейн,

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

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

Так, наприклад, скажімо 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.