javascript: utilizzo di una condizione in switch case


89

Scusa per quella stupida domanda. Come posso utilizzare una condizione per un caso nell'elemento linguaggio switch-case javascript? Come nell'esempio seguente, un caso dovrebbe corrispondere quando la variabile liCountè <= 5 e> 0; tuttavia, il mio codice non funziona:

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

Grazie per qualsiasi consiglio!


4
usa le istruzioni if ​​invece se vuoi farlo ..
Naftali aka Neal

3
Non dovresti ignorare tutti quelli che ti dicono di usare ifs, perché hanno ragione. Questa è una terribile applicazione di switch.
Lincolnk

Non posso credere che questa soluzione non sia stata fornita. Puoi farlo, l'istruzione deve solo valutare il valore nella clausola switch. Quindi questo funzionerebbe: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

Risposte:


291

Funziona:

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

Una versione precedente di questa risposta considerava le parentesi il colpevole. In verità, le parentesi qui sono irrilevanti: l'unica cosa necessaria è switch(true){...}e affinché le espressioni del tuo caso vengano valutate come booleane.

Funziona perché il valore che diamo all'interruttore viene utilizzato come base per il confronto. Di conseguenza, le espressioni case, valutando anche booleani, determineranno quale caso viene eseguito. Potrebbe anche capovolgere questo, e passare switch(false){..}e fare in modo che le espressioni desiderate valutino false invece che vere .. ma personalmente preferisco trattare condizioni che valutano veridicità. Tuttavia, funziona anche lui, quindi vale la pena tenerlo a mente per capire cosa sta facendo.

Ad esempio: se liCount è 3, il primo confronto è true === (liCount == 0), il che significa che il primo caso è falso. L'interruttore passa quindi al caso successivo true === (liCount<=5 && liCount>0). Questa espressione restituisce true, il che significa che questo caso viene eseguito e termina in break. Ho aggiunto parentesi qui per renderlo più chiaro, ma sono opzionali, a seconda della complessità della tua espressione.

È piuttosto semplice e un modo pulito (se si adatta a ciò che stai cercando di fare) per gestire una lunga serie di condizioni, dove forse una lunga serie di condizioni ìf() ... else if() ... else if () ...potrebbe introdurre molto rumore visivo o fragilità.

Usare con cautela, perché è un pattern non standard, nonostante sia un codice valido.


9
Penso che avresti bisogno di avere switch(true) {, e case liCount == 0:giusto? Altrimenti questo confronto è liCount == (liCount <=5 && liCount > 0).
loganfsmyth

33
Sai, non è perché puoi che dovresti . Questo è qualcosa che deve essere ucciso con il fuoco.
JBert

21
Fa parte del linguaggio - di conseguenza, conoscerlo è meglio che no. Chiaramente, non sarebbe appropriato per ogni situazione, ma a livello puramente soggettivo, penso che questo sia un approccio interessante, e più leggibile / meno fragile di una serie di ifs / elif in questo caso. La cosa importante da ricordare è che la codifica è un'espressione di intenti, unita al gusto e alla pratica. Avere più opzioni per esprimersi chiaramente in codice non è mai una cosa negativa.
dmp

1
Per me questo è stato molto utile e un modo molto carino per organizzare la mia logica in cui avevo bisogno di usare un nome di variabile più e più volte in base a una condizione if, ma era uno scenario di tipo n + 1 quindi il fatto che il caso dell'istruzione switch senza una pausa si sposterà sulla riga successiva di seguito è stata estremamente utile.
Joseph Astrahan

2
Hai persino aperto gli occhi per vedere quale sarebbe stato il risultato se l'espressione switch fosse falsa in questo modo switch(false) { }
bello hargbola

24

Hai modo troppo complicata che. Scrivilo con istruzioni if ​​invece in questo modo:

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

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

Oppure, se ChaosPandion sta cercando di ottimizzare il più possibile:

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

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

Dovevi andare e uno su di me. :)
ChaosPandion

Abbiamo scritto i nostri post contemporaneamente. Non ho visto il tuo finché non l'ho già pubblicato. Sembra che tu stia esagerando ora ...
Eric

Wow, non ho davvero pensato ai condizionali eccessivamente complessi.
ChaosPandion

1
@ Caos: sì, probabilmente è esagerato. Dovresti anche aggiungere un controllo null a setLayoutState: P.
Eric

@Eric - alcuni programmatori con più giri di programmazione dietro di me hanno detto: "solo perché puoi scrivere Javascript senza parentesi graffe (e - in effetti con cura - punto e virgola) non significa che dovresti", Ma ho appena riscritto alcuni multipli if come nel tuo esempio comunque, quindi grazie - funziona bene finché non c'è più di una riga da eseguire dopo la condizione. La soluzione ternaria era un ponte troppo lontano per me, però ...
Dave Everitt

7

Vuoi usare le istruzioni if:

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

7

Vedi la risposta di dmp di seguito. Eliminerei questa risposta se potessi, ma è stata accettata, quindi questa è la prossima cosa migliore :)

Non puoi. Gli interpreti JS richiedono di confrontare con l'istruzione switch (ad esempio, non esiste un'istruzione "case when"). Se vuoi davvero farlo, puoi semplicemente creare if(){ .. } else if(){ .. }blocchi.


9
Non è corretto. Ecco una demo che ne mostra il funzionamento: jsfiddle.net/Ender/fr3wL . Lo standard ECMAScript afferma esplicitamente che ciò è consentito: docstore.mik.ua/orelly/webprog/jscript/ch06_05.htm#FOOTNOTE-18
Ender

3
@Ender In che modo è lo stesso di quello che haemse sta cercando di fare?
Aistina

@Aistina Non lo è. Poiché le condizioni del suo caso producono un valore vero / falso piuttosto che un valore numerico, haemse avrebbe dovuto testare i suoi casi per un valore veritiero (come suggerito dalla risposta di danp), piuttosto che testare contro il valore numerico di liCount. Stavo semplicemente facendo notare che l'affermazione originale di cwolves che "JS Interpreters richiede che le istruzioni case siano valori statici" non era corretta. cwolves da allora ha rivisto questa dichiarazione, quindi il mio commento non è più pertinente.
Ender

Perché questo non risponde alla domanda. Non ha chiesto un modo diverso per farlo, ha chiesto di far funzionare il caso dell'interruttore come vuole. "Fallo in qualche altro modo" non è quasi mai una risposta corretta, nonostante noi quasi sempre pensiamo che lo sia. Pensiamo sempre di avere un modo migliore, ma non è così che vuole farlo, rendendo questa risposta semplicemente sbagliata.
Jasmine

@ Jasmine - "Non puoi, quindi fallo in un altro modo" è perfettamente valido, se è corretto . La mia risposta è stata sottovalutata perché è semplicemente sbagliata :) Come ha sottolineato @danp, puoi semplicemente passare contro truee funziona. Ma ha più di 3 anni, quindi non mi interessa davvero.
Mark Kahn

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

funzionerà in JavaScript fintanto che le tue condizioni restituiscono booleanvalori corretti , ma non ha molti vantaggi rispetto alle else ifistruzioni.


Funzionerà se passo un numero intero nell'istruzione 10switch? nel mio caso non funziona non so quale sia la ragione.
Pardeep Jain

10 !== true, quindi no. C'è qualche variabile che potrebbe avere il valore 10? Se x, allora case x === 10:funzionerebbe.
Mike Samuel

Ma dovrebbe funzionare come le altre istruzioni, ad esempio se usi il if (10) {..}flusso dovrebbe passare nella Ifcondizione, non è vero? perché 10 o qualsiasi numero intero tranne 0 verrà trattato come valore vero e consentirà di entrare nella condizione. Non sono sicuro di cosa c'è che non va con la sua dichiarazione qui.
Pardeep Jain

1
@PardeepJain, switchsemplicemente non funziona come if. ifverifica se la condizione è veritiera . switchtest se l'espressione dopo la switchè ===( CaseClauseIsSelected passaggio 4 ) al valore della espressione dopo case.
Mike Samuel,

Ohh così, grazie. Questo era totalmente nuovo per me. @Mike
Pardeep Jain


4

Se è quello che vuoi fare, sarebbe meglio usare le ifdichiarazioni. Per esempio:

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

Il tuo codice non funziona perché non sta facendo quello che ti aspetti che faccia. I blocchi di commutazione prendono un valore e confrontano ogni caso con il valore dato, cercando l'uguaglianza. Il valore di confronto è un numero intero, ma la maggior parte delle espressioni del caso si risolve in un valore booleano.

Quindi, ad esempio, dì liCount = 2. Il tuo primo caso non corrisponderà, perché 2 != 0. Il tuo secondo caso (liCount<=5 && liCount>0)restituisce true, ma 2 != true, quindi neanche questo caso corrisponderà.

Per questo motivo, come molti altri hanno detto, dovresti utilizzare una serie di if...then...else ifblocchi per farlo.


2

se i valori possibili sono numeri interi, puoi raggruppare i casi. Altrimenti, usa 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

Notare che non passiamo il punteggio allo switch ma è vero. Il valore che diamo allo switch viene utilizzato come base per il confronto.

L'esempio seguente mostra come aggiungere condizioni nel case: senza alcuna istruzione 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

Sebbene nel particolare esempio della domanda del PO, switchnon sia appropriato, c'è un esempio in cui il passaggio è ancora appropriato / vantaggioso, ma sono necessarie anche altre espressioni di valutazione. Ciò può essere ottenuto utilizzando la clausola predefinita per le espressioni:

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

0

È possibile utilizzare il metodo di ricaduta in caso di commutazione.

const x = 'Welcome';

switch (x) {
  case 'Come':
    console.log(1)
    break;

  case 'Welcome':
  case 'Wel':
  case 'come':
    console.log(2)
    break;

  case 'Wel':
    console.log(3)
    break;

  default:
    break;
}

    
> Result => 2
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.