javascript: używanie warunku w przypadku przełącznika

88

Przepraszam za to głupie pytanie. Jak mogę użyć warunku dla przypadku w elemencie języka przełączania wielkości liter javascript? Podobnie jak w poniższym przykładzie, wielkość liter powinna być zgodna, gdy zmienna liCountma wartość <= 5 i> 0; jednak mój kod nie działa:

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

Dzięki za każdą radę!

haemse
źródło
4
użyj zamiast tego instrukcji if, jeśli chcesz to zrobić ...
Naftali aka Neal
3
Nie powinieneś ignorować wszystkich, którzy mówią ci, abyś używał ifs, ponieważ mają rację. To okropne zastosowanie switch.
Lincolnk,
Nie mogę uwierzyć, że to rozwiązanie nie zostało dostarczone. Możesz to zrobić, instrukcja musi po prostu oszacować wartość w klauzuli switch. Więc to zadziała: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,

Odpowiedzi:

286

To działa:

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

Poprzednia wersja tej odpowiedzi uważała nawiasy za winowajcę. Prawdę mówiąc, nawiasy nie mają tu znaczenia - jedyne, co jest potrzebne, to switch(true){...}aby wyrażenia przypadków były obliczane na wartości logiczne.

Działa, ponieważ wartość, którą podajemy przełącznikowi, jest używana jako podstawa do porównania. W konsekwencji wyrażenia przypadków, również obliczane na wartości logiczne, określają, który przypadek jest uruchamiany. Mógłby to również odwrócić i przekazać switch(false){..}i sprawić, że pożądane wyrażenia zostaną ocenione na fałsz zamiast na prawdę, ale osobiście wolę radzić sobie z warunkami, które oceniają prawdziwość. Jednak to też działa, więc warto pamiętać, aby zrozumieć, co robi.

Np .: jeśli liCount wynosi 3, pierwsze porównanie jest true === (liCount == 0), co oznacza, że ​​pierwszy przypadek jest fałszywy. Przełącznik przechodzi następnie do następnej sprawy true === (liCount<=5 && liCount>0). To wyrażenie zwraca wartość true, co oznacza, że ​​ten przypadek jest uruchamiany i kończy się na break. Dodałem tutaj nawiasy, aby było jaśniej, ale są one opcjonalne, w zależności od złożoności Twojego wyrażenia.

Jest to dość proste i zgrabny sposób (jeśli pasuje do tego, co próbujesz zrobić) radzenia sobie z długą serią warunków, w których być może długa seria ìf() ... else if() ... else if () ...może wprowadzić dużo wizualnego szumu lub kruchości.

Używaj ostrożnie, ponieważ jest to niestandardowy wzorzec, mimo że jest prawidłowym kodem.

dmp
źródło
9
Myślę, że musiałbyś mieć switch(true) {, i case liCount == 0:prawda? W przeciwnym razie to porównanie jest liCount == (liCount <=5 && liCount > 0).
loganfsmyth
33
Wiesz, to nie dlatego, że możesz , że powinieneś . To jest coś, co trzeba zabić ogniem.
JBert,
21
To część języka - dlatego lepiej o nim wiedzieć, niż nie. Oczywiście nie byłoby to odpowiednie dla każdej sytuacji, ale na poziomie czysto subiektywnym myślę, że jest to interesujące podejście i bardziej czytelne / mniej kruche niż seria if / elif w tym przypadku. Ważną rzeczą do zapamiętania jest to, że kodowanie jest wyrazem intencji połączonym ze smakiem i praktyką. Posiadanie większej liczby możliwości wyraźnego wyrażenia siebie w kodzie nigdy nie jest złe.
dmp
1
Dla mnie był to bardzo przydatny i bardzo fajny sposób na zorganizowanie mojej logiki, w której musiałem wielokrotnie używać nazwy zmiennej w oparciu o warunek if, ale był to scenariusz typu n + 1, więc fakt, że instrukcja przełączania bez przerwa przeniesiona do następnej linii poniżej była niezwykle przydatna.
Joseph Astrahan
2
Otworzyłeś nawet nasze oczy, aby zobaczyć, jaki byłby wynik, gdyby wyrażenie przełącznika było fałszywe switch(false) { }
bello hargbola
24

Masz sposób zbyt skomplikowana, że. Zamiast tego napisz go za pomocą instrukcji if w ten sposób:

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

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

Lub, jeśli ChaosPandion próbuje zoptymalizować tak bardzo, jak to możliwe:

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

$('#UploadList').data('jsp').reinitialise();
Eric
źródło
Musiałeś iść i jeden do mnie. :)
ChaosPandion
Pisaliśmy nasze posty jednocześnie. Nie widziałem twojego, dopóki nie opublikowałem. Wygląda na to, że teraz przesadzasz ...
Eric
Wow, tak naprawdę nie myślałem o zbyt złożonych warunkach warunkowych.
ChaosPandion,
1
@Chaos: tak, to prawdopodobnie przesada. Musiałbyś również dodać sprawdzenie zerowe do setLayoutState: P.
Eric
@Eric - niektórzy programiści z większą liczbą okrążeń programowania niż ja mówię: „tylko dlatego, że można pisać w Javascript bez nawiasów klamrowych (i - właściwie ostrożnie - średników) nie oznacza, że ​​powinniście”, ale ja po prostu przepisałem kilka if tak jak w twoim przykładzie, więc dzięki - działa dobrze, dopóki po warunku nie ma więcej niż jednej linii do wykonania. Rozwiązanie trójskładnikowe było jednak dla mnie o krok za daleko…
Dave Everitt
7

Chcesz użyć instrukcji if:

if (liCount === 0) {
    setLayoutState('start');
} else if (liCount <= 5) {
    setLayoutState('upload1Row');
} else if (liCount <= 10) {
    setLayoutState('upload2Rows');
}
$('#UploadList').data('jsp').reinitialise();  
ChaosPandion
źródło
7

Zobacz odpowiedź dmp poniżej. Skasowałbym tę odpowiedź, gdybym mógł, ale została zaakceptowana, więc to kolejna najlepsza rzecz :)

Nie możesz. Interpretatorzy JS wymagają porównania z instrukcją switch (np. Nie ma instrukcji „przypadek kiedy”). Jeśli naprawdę chcesz to zrobić, możesz po prostu zrobić if(){ .. } else if(){ .. }bloki.

Mark Kahn
źródło
9
To jest niepoprawne. Oto demo pokazujące, jak działa: jsfiddle.net/Ender/fr3wL . Standard ECMAScript wyraźnie stwierdza, że ​​jest to dozwolone: docstore.mik.ua/orelly/webprog/jscript/ch06_05.htm#FOOTNOTE-18
Ender
3
@Ender Jak to się ma do tego, co próbuje zrobić hemse?
Aistina
@Aistina To nie jest. Ponieważ warunki jego przypadku generują wartość prawda / fałsz, a nie wartość liczbową, haemse musiałby przetestować swoje przypadki pod kątem wartości prawdziwej (takiej jak sugerowana przez odpowiedź danpa), zamiast testować w odniesieniu do wartości liczbowej liCount. Zwróciłem tylko uwagę, że oryginalne stwierdzenie cwolves, że „Tłumacze JS wymagają, aby opisy przypadków były wartościami statycznymi” było niepoprawne. Od tego czasu cwolves zrewidował to oświadczenie, więc mój komentarz nie jest już aktualny.
Ender
Ponieważ to nie odpowiada na pytanie. Nie prosił o inny sposób, aby to zrobić, poprosił, aby przełącznik działał tak, jak chce. „Zrób to w inny sposób” prawie nigdy nie jest poprawną odpowiedzią, mimo że prawie zawsze myślimy, że tak. Zawsze myślimy, że mamy lepszy sposób, ale on nie chce tego robić, czyniąc tę ​​odpowiedź po prostu błędną.
Jasmine,
@Jasmine - „Nie możesz, więc zrób to w inny sposób” jest całkowicie poprawne, jeśli jest poprawne . Moja odpowiedź jest przegłosowana, ponieważ jest po prostu błędna :) Jak zauważył @danp, możesz po prostu się przełączyć truei to działa. Ale ma ponad 3 lata, więc nie obchodzi mnie to.
Mark Kahn,
5
switch (true) {
  case condition0:
    ...
    break;
  case condition1:
    ...
    break;
}

będzie działać w JavaScript, o ile twoje warunki zwrócą prawidłowe booleanwartości, ale nie ma wielu zalet w porównaniu z else ifinstrukcjami.

Mike Samuel
źródło
Czy to zadziała, jeśli przekażę jakąś liczbę całkowitą 10w instrukcji przełącznika? w moim przypadku nie działa, nie wiem, co jest przyczyną.
Pardeep Jain
10 !== true, więc nie. Czy jest jakaś zmienna, która może mieć wartość 10? Jeśli x, to case x === 10:będzie działać.
Mike Samuel
Ale powinno działać tak jak inne instrukcje, na przykład jeśli używasz if (10) {..}przepływu, powinien przejść w Ifwarunku, prawda? ponieważ 10 lub dowolna liczba całkowita poza 0 będzie traktowana jako wartość zgodna z prawdą i pozwoli na wejście w warunek. Nie jestem pewien, co jest nie tak z tym oświadczeniem przełącznika.
Pardeep Jain
1
@PardeepJain, switchpo prostu nie działa jak if. ifsprawdza, czy warunek jest prawdziwy . switchsprawdza, czy wyrażenie po switchis ===( CaseClauseIsSelected krok 4 ) do wartości wyrażenia po case.
Mike Samuel
O tak, dzięki. To było dla mnie zupełnie nowe. @Mike
Pardeep Jain
4

To jest przypadek, w którym powinieneś używać ifklauzul.

ThiefMaster
źródło
4

Jeśli tego chcesz, lepiej byłoby użyć ifinstrukcji. Na przykład:

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();
Naftali alias Neal
źródło
2

Twój kod nie działa, ponieważ nie robi tego, czego od niego oczekujesz. Bloki przełączające pobierają wartość i porównują każdy przypadek z podaną wartością, szukając równości. Twoja wartość porównawcza jest liczbą całkowitą, ale większość wyrażeń określających wielkość liter ma wartość logiczną.

Na przykład powiedz liCount = 2. Twój pierwszy przypadek nie będzie pasował, ponieważ2 != 0 . Twój drugi przypadek zostanie (liCount<=5 && liCount>0)oszacowany na true, ale 2 != true, więc ten przypadek również nie będzie pasował.

Z tego powodu, jak powiedziało wielu innych, powinieneś użyć do tego szeregu if...then...else ifbloków.

Ender
źródło
2

jeśli możliwe wartości są liczbami całkowitymi, możesz zebrać przypadki. W przeciwnym razie użyj 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();
kennebec
źródło
0

Zauważ, że nie przekazujemy wyniku do przełącznika, ale prawda. Wartość, którą podajemy przełącznikowi, służy jako podstawa do porównania.

Poniższy przykład pokazuje, jak możemy dodać warunki w przypadku: bez żadnych instrukcji 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;
}
Spodnie Harshit
źródło
0

Chociaż w tym konkretnym przykładzie pytania PO switchnie jest właściwe, istnieje przykład, w którym zmiana jest nadal odpowiednia / korzystna, ale wymagane są również inne wyrażenia oceny. Można to osiągnąć, używając domyślnej klauzuli dla wyrażeń:

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
    }
}
spikyjt
źródło