Javascript: Verwenden einer Bedingung im Schalterfall

85

Entschuldigung für diese dumme Frage. Wie kann ich eine Bedingung für einen Fall im Javascript Switch-Case-Sprachelement verwenden? Wie im folgenden Beispiel sollte ein Fall übereinstimmen, wenn die Variable liCount<= 5 und> 0 ist. Mein Code funktioniert jedoch nicht:

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

Vielen Dank für jeden Rat!

haemse
quelle
4
Verwenden Sie stattdessen if-Anweisungen, wenn Sie dies tun möchten.
Naftali aka Neal
3
Sie sollten nicht jeden ignorieren, der Ihnen sagt, dass Sie ifs verwenden sollen, weil sie Recht haben. Dies ist eine schreckliche Anwendung von switch.
Lincolnk
Ich kann nicht glauben, dass diese Lösung nicht bereitgestellt wurde. Sie können dies tun, die Anweisung muss nur den Wert in der switch-Klausel auswerten. Das würde also funktionieren: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

Antworten:

277

Das funktioniert:

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

In einer früheren Version dieser Antwort wurden die Klammern als Schuldige angesehen. In Wahrheit sind die Klammern hier irrelevant - das einzige, was notwendig ist, ist, switch(true){...}dass Ihre Fallausdrücke zu Booleschen Werten ausgewertet werden.

Es funktioniert, weil der Wert, den wir dem Schalter geben, als Grundlage für den Vergleich verwendet wird. Folglich bestimmen die Fallausdrücke, die auch nach Booleschen Werten ausgewertet werden, welcher Fall ausgeführt wird. Könnte dies auch umkehren und bestehen switch(false){..}und die gewünschten Ausdrücke als falsch anstatt als wahr bewerten lassen. Ich persönlich bevorzuge es jedoch, mit Bedingungen umzugehen, die als wahrheitsgetreu bewertet werden. Es funktioniert jedoch auch, daher sollten Sie bedenken, um zu verstehen, was es tut.

Beispiel: Wenn liCount 3 ist, ist der erste Vergleich true === (liCount == 0), was bedeutet, dass der erste Fall falsch ist. Der Schalter fährt dann mit dem nächsten Fall fort true === (liCount<=5 && liCount>0). Dieser Ausdruck wird als wahr ausgewertet, was bedeutet, dass dieser Fall ausgeführt wird und am endet break. Ich habe hier Klammern hinzugefügt, um es klarer zu machen, aber sie sind optional, abhängig von der Komplexität Ihres Ausdrucks.

Es ist ziemlich einfach und eine gute Möglichkeit (wenn es zu dem passt, was Sie versuchen), mit einer langen Reihe von Bedingungen umzugehen, bei denen eine lange Reihe von ìf() ... else if() ... else if () ...möglicherweise viel visuelles Rauschen oder Zerbrechlichkeit mit sich bringt.

Seien Sie vorsichtig, da es sich trotz gültigen Codes um ein nicht standardmäßiges Muster handelt.

dmp
quelle
9
Ich denke, Sie müssten haben switch(true) {, und case liCount == 0:richtig? Ansonsten ist dieser Vergleich liCount == (liCount <=5 && liCount > 0).
Loganfsmyth
33
Sie wissen, es ist nicht, weil Sie können, dass Sie sollten . Dies ist etwas, das mit Feuer getötet werden muss.
JBert
20
Es ist Teil der Sprache - folglich ist es besser als nicht, darüber Bescheid zu wissen. Natürlich wäre es nicht für jede Situation angemessen, aber auf rein subjektiver Ebene halte ich dies für einen interessanten Ansatz und in diesem Fall lesbarer / weniger fragil als eine Reihe von Wenns / Elfen. Wichtig ist, dass das Codieren ein Ausdruck der Absicht ist, gepaart mit Geschmack und Übung. Es ist nie schlecht, mehr Optionen zu haben, um sich klar im Code auszudrücken.
dmp
1
Für mich war dies sehr nützlich und eine sehr gute Möglichkeit, meine Logik so zu organisieren, dass ich einen Variablennamen basierend auf einer if-Bedingung immer wieder verwenden musste, aber es war ein Szenario vom Typ n + 1, also die Tatsache, dass switch-Anweisung ohne Eine Pause in der nächsten Zeile unten war von entscheidender Bedeutung.
Joseph Astrahan
2
Sie haben sogar unsere Augen geöffnet, um zu sehen, was das Ergebnis gewesen wäre, wenn der Schalterausdruck so falsch wäre switch(false) { }
bello hargbola
23

Sie haben das viel zu kompliziert gemacht. Schreiben Sie es stattdessen mit if-Anweisungen wie folgt:

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

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

Oder wenn ChaosPandion versucht, so viel wie möglich zu optimieren:

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

$('#UploadList').data('jsp').reinitialise();
Eric
quelle
Du musstest mich eins machen. :)
ChaosPandion
Wir haben unsere Beiträge gleichzeitig geschrieben. Ich habe deine erst gesehen, als ich sie bereits gepostet hatte. Sie scheinen es jetzt zu übertreiben ...
Eric
Wow, ich habe nicht wirklich über die übermäßig komplexen Bedingungen nachgedacht.
ChaosPandion
1
@Chaos: Ja, das übertreibt es wahrscheinlich. Sie müssten auch einen Null-Check hinzufügen setLayoutState: P.
Eric
@Eric - einige Programmierer mit mehr Programmierrunden als ich gesagt habe: "Nur weil Sie Javascript ohne geschweifte Klammern (und - mit Vorsicht - Semikolons) schreiben können, heißt das nicht, dass Sie es sollten", aber ich habe nur einige mehrfach umgeschrieben Wenn Anweisungen wie in Ihrem Beispiel sowieso, also danke - funktioniert einwandfrei, bis nach der Bedingung mehr als eine Zeile ausgeführt werden muss. Die ternäre Lösung war mir allerdings eine Brücke zu weit…
Dave Everitt
7

Sie möchten if-Anweisungen verwenden:

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

Siehe die Antwort von dmp unten. Ich würde diese Antwort löschen, wenn ich könnte, aber sie wurde akzeptiert, also ist dies das nächstbeste :)

Das kannst du nicht. JS-Interpreter verlangen, dass Sie mit der switch-Anweisung vergleichen (z. B. gibt es keine "case when" -Anweisung). Wenn Sie dies wirklich tun möchten, können Sie einfach if(){ .. } else if(){ .. }Blöcke erstellen.

Mark Kahn
quelle
9
Das ist falsch Hier ist eine Demo, die zeigt, wie es funktioniert: jsfiddle.net/Ender/fr3wL . Der ECMAScript-Standard besagt ausdrücklich, dass dies zulässig ist: docstore.mik.ua/orelly/webprog/jscript/ch06_05.htm#FOOTNOTE-18
Ender
3
@Ender Wie ist das das gleiche wie das, was Haemse versucht zu tun?
Aistina
@Aistina Es ist nicht. Da seine Fallbedingungen eher einen wahren / falschen Wert als einen numerischen Wert ergeben, hätte Haemse seine Fälle auf einen wahrheitsgemäßen Wert testen müssen (wie in Danps Antwort vorgeschlagen), anstatt ihn gegen den numerischen Wert von zu testen liCount. Ich habe lediglich darauf hingewiesen, dass die ursprüngliche Aussage von cwolves, dass "JS-Interpreter erfordern, dass case-Anweisungen statische Werte sind", falsch ist. cwolves hat diese Aussage inzwischen überarbeitet, sodass mein Kommentar nicht mehr relevant ist.
Ender
Weil dies die Frage nicht beantwortet. Er fragte nicht nach einem anderen Weg, sondern darum, dass der Schaltkasten so funktioniert, wie er es möchte. "Mach es anders" ist fast nie eine richtige Antwort, obwohl wir so ziemlich immer denken, dass es so ist. Wir denken immer, wir haben einen besseren Weg, aber so will er es nicht machen, was diese Antwort einfach falsch macht.
Jasmine
@Jasmine - "Du kannst nicht, also mach es anders" ist vollkommen gültig, wenn es richtig ist . Meine Antwort wird abgelehnt, weil es einfach falsch ist :) Wie @danp betonte, kann man einfach dagegen wechseln trueund es funktioniert. Aber es ist über 3 Jahre alt, also ist es mir eigentlich egal.
Mark Kahn
5
switch (true) {
  case condition0:
    ...
    break;
  case condition1:
    ...
    break;
}

funktioniert in JavaScript, solange Ihre Bedingungen die richtigen booleanWerte zurückgeben, hat jedoch nicht viele Vorteile gegenüber else ifAnweisungen.

Mike Samuel
quelle
Wird es funktionieren, wenn ich eine ganzzahlige Aussage 10in der switch-Anweisung übergebe? in meinem Fall nicht funktionieren nicht sicher, was der Grund ist.
Pardeep Jain
10 !== true, also nein. Gibt es eine Variable, die den Wert haben könnte 10? Wenn x, dann case x === 10:würde es funktionieren.
Mike Samuel
Aber es sollte wie andere Anweisungen funktionieren, zum Beispiel, wenn Sie if (10) {..}Flow verwenden, sollte die IfBedingung übergeben werden, nicht wahr? weil 10 oder eine ganze Zahl außer 0 als wahrheitsgemäßer Wert behandelt wird und es erlaubt, in die Bedingung einzutreten. Ich bin mir nicht sicher, was mit der switch-Anweisung hier falsch ist.
Pardeep Jain
1
@PardeepJain, switchfunktioniert einfach nicht so if. ifprüft, ob die Bedingung wahr ist . Testetswitch , ob der Ausdruck nach dem switchist ===( CaseClauseIsSelected Schritt 4 ) auf den Wert des Ausdrucks nach case.
Mike Samuel
Ohh so, danke. Das war völlig neu für mich. @ Mike
Pardeep Jain
4

In diesem Fall sollten Sie ifKlauseln verwenden.

DiebMaster
quelle
4

Wenn Sie dies tun möchten, ist es besser, ifAnweisungen zu verwenden . Beispielsweise:

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
quelle
2

Ihr Code funktioniert nicht, weil er nicht das tut, was Sie von ihm erwarten. Schalterblöcke nehmen einen Wert auf und vergleichen jeden Fall mit dem angegebenen Wert, um Gleichheit zu erreichen. Ihr Vergleichswert ist eine Ganzzahl, aber die meisten Ihrer Fallausdrücke werden in einen booleschen Wert aufgelöst.

So sagen wir zum Beispiel liCount = 2. Ihr erster Fall wird nicht übereinstimmen, weil 2 != 0. Ihr zweiter Fall wird (liCount<=5 && liCount>0)mit true, aber bewertet 2 != true, sodass dieser Fall auch nicht übereinstimmt.

Aus diesem Grund sollten Sie, wie viele andere gesagt haben, eine Reihe von if...then...else ifBlöcken verwenden, um dies zu tun.

Ender
quelle
2

Wenn die möglichen Werte Ganzzahlen sind, können Sie Fälle zusammenfassen. Verwenden Sie andernfalls 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
quelle
0

Beachten Sie, dass wir keine Punktzahl an den Switch übergeben, sondern true. Der Wert, den wir dem Schalter geben, wird als Vergleichsbasis verwendet.

Das folgende Beispiel zeigt, wie wir im Fall Bedingungen hinzufügen können: ohne if-Anweisungen.

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;
}
Harshit Pant
quelle
0

Obwohl in dem speziellen Beispiel der OP-Frage dies switchnicht angemessen ist, gibt es ein Beispiel, in dem ein Wechsel immer noch angemessen / nützlich ist, aber auch andere Bewertungsausdrücke erforderlich sind. Dies kann erreicht werden, indem die Standardklausel für die Ausdrücke verwendet wird:

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
quelle