Cambia istruzione per più casi in JavaScript


768

Ho bisogno di più casi nell'istruzione switch in JavaScript, qualcosa del tipo:

switch (varName)
{
   case "afshin", "saeed", "larry": 
       alert('Hey');
       break;

   default: 
       alert('Default case');
       break;
}

Come lo posso fare? Se non c'è modo di fare qualcosa del genere in JavaScript, voglio sapere una soluzione alternativa che segua anche il concetto DRY .


5
A chi ha votato per chiudere questa domanda. Ha più di 5 anni e ha una risposta accettata: perché lo stretto voto?
— surfmuggle,

@surfmuggle perché non è necessario aggiungere altre risposte.
— Afshin Mehrabani,

7
@AfshinMehrabani forse può essere protetto, non chiuso?
— evolutionxbox,

Risposte:


1510

Utilizzare la funzione fall-through switchdell'istruzione. Un caso corrispondente verrà eseguito fino a quando non viene trovata una break(o la fine switchdell'istruzione), quindi è possibile scriverla come:

switch (varName)
{
   case "afshin":
   case "saeed":
   case "larry": 
       alert('Hey');
       break;

   default: 
       alert('Default case');
}


2
In qualche modo funziona per me in Chrome, nella console javascript: switch('10') { case 1, '10': console.log('ok') }stampeok
— nafg

8
@nafg: prova switch(1). L'etichetta qui è solo un'espressione virgola.
— kennytm,

4
@Barney No, senza l'interruzione puoi passare al caso successivo.
— Seiyria,

1
@Seiyira per definizione, non c'è nessun caso successivo dopo l'ultimo. Inoltre, è un valore predefinito.
— Barney,

101

Funziona in JavaScript normale

function theTest(val) {
  var answer = "";
  switch( val ) {
    case 1: case 2: case 3:
      answer = "Low";
      break;
    case 4: case 5: case 6:
      answer = "Mid";
      break;
    case 7: case 8: case 9:
      answer = "High";
      break;
    default:
      answer = "Massive or Tiny?";
  } 
  return answer;  
}

theTest(9);

Saluti.


13
@believesInSanta è letteralmente solo un normale caso con una strana formattazione (spazi anziché nuove righe)
— Mihail Malostanidis

42

Ecco un approccio diverso, evitando del switchtutto l' affermazione:

var cases = {
  afshin: function() { alert('hey'); },
  _default: function() { alert('default'); }
};
cases.larry = cases.saeed = cases.afshin;

cases[ varName ] ? cases[ varName ]() : cases._default();

5
Preferisco decisamente questa versione. Fall through è una funzione soggetta a bug switch ... case. È troppo facile dimenticare breakun'affermazione e se si usa cadere intenzionalmente, quelle breakaffermazioni dimenticate possono essere molto difficili da individuare. Questa versione di ricerca del metodo ha anche molte grandi funzionalità che switch ... casemancano, come l'estensibilità dinamica o la possibilità di sostituire completamente l'oggetto per realizzare il cambio di modalità. È anche più facile organizzarsi in modo pulito e può portare a codice più gestibile. Vedi ericleads.com/2012/12/switch-case-considered-harmful
— Eric Elliott

31
Aggiungo sempre un commento //fallthroughal posto di breakogni volta che ometto intenzionalmente il break. Ciò aiuta a identificare quando è un errore e quando è intenzionale.
— Mnebuerquo,

18
Approccio intuitivo Tuttavia, per leggibilità, consiglierei di usare l'istruzione switch nativa.
— contactmatt

39
Si può sempre graffiare l'orecchio sinistro passando la mano destra attraverso la parte posteriore del collo ... (scusate il mio inglese, intendo dire: "si può sempre complicare il più possibile le cose ... in questo caso, evitando l'istruzione switch a favore di questa complicata soluzione non sembra essere la cosa giusta da fare ...)
— Clint Eastwood,

25
Sono davvero sorpreso dal fatto che questo abbia ottenuto 34 voti in più. In termini di leggibilità e manutenibilità, questo è assolutamente orribile. Se voglio vedere quali condizioni attiveranno qualcosa, un'affermazione del caso è incredibilmente semplice e facile da vedere guardando le etichette. D'altra parte, la tua versione richiederebbe che qualcuno legga praticamente ogni singola riga e veda cosa ti è stato assegnato. Ciò peggiora anche il numero di casi che desideri abbinare.
— michael

21

In Javascript per assegnare più casi in uno switch, dobbiamo definire different case without break inbetweencome indicato di seguito:

   <script>
      function checkHere(varName){
        switch (varName)
           {
           case "saeed":
           case "larry":
           case "afshin":
                alert('Hey');
                break;
          case "ss":
               alert('ss');
               break;
         default:
               alert('Default case');
               break;
       }
      }
     </script>

Vedi esempio fare clic sul collegamento


5
È una tecnica comune in una pletora di lingue, non vincolata a JS
— drAlberT

13

Se stai usando ES6, puoi farlo:

if (['afshin', 'saeed', 'larry'].includes(varName)) {
   alert('Hey');
} else {
   alert('Default case');
}

O per le versioni precedenti di JavaScript, puoi farlo:

if (['afshin', 'saeed', 'larry'].indexOf(varName) !== -1) {
   alert('Hey');
} else {
   alert('Default case');
}

Nota che questo non funzionerà nei browser IE più vecchi, ma potresti sistemare le cose abbastanza facilmente. Vedere la domanda per determinare se la stringa è nell'elenco in javascript per ulteriori informazioni.


Qual è il vantaggio di questo rispetto a un interruttore?
— Bryce Snyder,

@BryceSnyder la differenza tra un'espressione e un'affermazione? Meno battitura a macchina? Meno linee verticali consumate? Maggiore potere espressivo attraverso la sintonia e la densità della rappresentazione? Semantica migliore attraverso la includesparola? Fai la tua scelta.
— ErikE,

7

Nel nodo sembra che ti sia permesso di fare questo:

data = "10";
switch(data){
case "1": case "2": case "3": //put multiple cases on the same line to save vertical space.
   console.log("small"); break;
case "10": case "11": case "12":
   console.log("large"); break;
default:
   console.log("strange");
   break;
}

Ciò rende il codice molto più compatto in alcuni casi.


1
Penso che la sintassi sia la stessa degli altri ambienti JS.
— Afshin Mehrabani,

1
@AfshinMehrabani Potrebbe essere, l'ho provato solo nel contesto nodejs.
— Automatico

Sì. Mi piace salvare lo spazio verticale!
— Canale

7

Aggiungendo e chiarendo la risposta di Stefano, è possibile utilizzare espressioni per impostare dinamicamente i valori per le condizioni nello switch, ad esempio:

var i = 3
switch (i) {
    case ((i>=0 && i<=5)?i:-1): console.log('0-5'); break;
    case 6: console.log('6');
}

Quindi, nel tuo problema, potresti fare qualcosa del tipo:

var varName = "afshin"
switch (varName) {
    case (["afshin", "saeed", "larry"].indexOf(varName)+1 && varName):
      console.log("hey");
      break;

    default:
      console.log('Default case');
}

sebbene non sia così ASCIUTTO ..


non ancora testato ma sarebbe interessante modificarlo varNameall'interno dell'espressione case, aspettatevi che varName sia memorizzato nella cache.
— Valen,

5

puoi usare l' operatore ' in ' ...
si basa sull'invocazione di oggetti / hash ...
quindi è veloce come javascript può essere ...

// assuming you have defined functions f(), g(a) and h(a,b) 
// somewhere in your code
// you can define them inside the object but... 
// the code becomes hard to read, I prefer this way

o = { f1:f, f2:g, f3:h };

// if you use "STATIC" code can do:
o['f3']( p1, p2 )

// if your code is someway "DYNAMIC", to prevent false invocations
// m brings the function/method to be invoked (f1, f2, f3)
// and you can rely on arguments[] to solve any parameter problems
if ( m in o ) o[m]()

Divertiti, ZEE


come si collega questo passaggio? puoi chiarirlo?
— Z. Khullah,

perché vorresti rendere il tuo codice "difficile da leggere". La prima cosa che mi è stato detto come programmatore è stato scrivere il codice con la mentalità che la persona successiva che legge il tuo codice è un'ascia che brandisce serial killer e odia non essere in grado di capire il codice.
— MattE

Ciao Matt ... Lo sto presentando come una prova del concetto ... comunque questo modulo ti offre più funzionalità e flessibilità ... e lo usi solo se vuoi ... o se trovi un vincolo nel tuo solita forma di fare le cose ... considera ir come un altro strumento nella tua cassetta degli attrezzi del programmatore ...
— ZEE

5

Io uso così:

switch (true){
     case /Pressure/.test(sensor):{
        console.log('Its pressure!');
        break;
     }
     case /Temperature/.test(sensor):{
        console.log('Its temperature!');
        break;
     }
}

Non hai bisogno di usare la gbandiera, poiché stai usando le regex solo una volta e le butti via. In effetti, se li tenessi al di fuori della funzione, la gbandiera ti danneggerebbe provando a far corrispondere un indice diverso da 0 sui successivi .test(. Ho anche risolto un errore di battitura in cui il caso switch era su sensorvariabile e non truecostante per la corrispondenza delle espressioni booleane. Vedi la modifica.
— Mihail Malostanidis,

Ho usato questo formato per testare i tipi di file. Esempio:case /officedocument/.test(type) && /presentation/.test(type): iconClass = "far fa-file-powerpoint red"; break;
— tbone849,

4

Dipende. Switch valuta una volta e una sola volta. In caso di corrispondenza, tutte le successive dichiarazioni del caso fino a quando non si "rompono", indipendentemente da ciò che dice il caso.

var onlyMen = true;
var onlyWomen = false;
var onlyAdults = false;
 
 (function(){
   switch (true){
     case onlyMen:
       console.log ('onlymen');
     case onlyWomen:
       console.log ('onlyWomen');
     case onlyAdults:
       console.log ('onlyAdults');
       break;
     default:
       console.log('default');
   }
})(); // returns onlymen onlywomen onlyadults
<script src="https://getfirebug.com/firebug-lite-debug.js"></script>


3

Mi piace questo per chiarezza e sintassi DRY.

varName = "larry";

switch (true)
{
    case ["afshin", "saeed", "larry"].includes(varName) :
       alert('Hey');
       break;

    default: 
       alert('Default case');

}

2

Vedo che ci sono molte buone risposte qui, ma cosa succede se dobbiamo controllare più di 10 casi? Ecco il mio approccio:

 function isAccessible(varName){
     let accessDenied = ['Liam','Noah','William','James','Logan','Benjamin',
                        'Mason','Elijah','Oliver','Jacob','Daniel','Lucas'];
      switch (varName) {
         case (accessDenied.includes(varName)?varName:null): 
             return 'Access Denied!';
         default:
           return 'Access Allowed.';
       }
    }

    console.log(isAccessible('Liam'));

1
Questo è un abuso dell'istruzione switch. Basta if (accessDenied.includes(varName)) return 'Access Denied!'; return 'Access Allowed.'è più che sufficiente.
— Mihail Malostanidis,

2

Il problema con gli approcci di cui sopra è che devi ripetere i vari cases ogni volta che chiami la funzione che ha il switch. Una soluzione più solida è quella di avere una mappa o un dizionario .

Ecco un esempio

// the Map, divided by concepts
var dictionary = {
  timePeriod: {
    'month': [1, 'monthly', 'mensal', 'mês'],
    'twoMonths': [2, 'two months', '2 motnhs', 'bimestral', 'bimestre'],
    'trimester': [3, 'trimesterly', 'quarterly', 'trimestral'],
    'semester': [4, 'semesterly', 'semestral', 'halfyearly'],
    'year': [5, 'yearly', 'anual', 'ano']
  },
  distance: {
    'km': [1, 'kms', 'kilometre', 'kilometers', 'kilometres'],
    'mile': [2, 'mi', 'miles'],
    'nordicMile': [3, 'nordic mile', 'mil(10km)', 'scandinavian mile']
  },
  fuelAmount: {
    'ltr': [1, 'l', 'litre', 'Litre', 'liter', 'Liter'],
    'gal(imp)': [2, 'imp gallon', 'imperial gal', 'gal(UK)'],
    'gal(US)': [3, 'US gallon', 'US gal'],
    'kWh': [4, 'KWH']
  }
};

//this function maps every input to a certain defined value
function mapUnit (concept, value) {
  for (var key in dictionary[concept]) {
    if (key === value || 
      dictionary[concept][key].indexOf(value) !== -1) {
      return key
    }
  }
  throw Error('Uknown "'+value+'" for "'+concept+'"')
}

//you would use it simply like this
mapUnit("fuelAmount", "ltr") // => ltr
mapUnit("fuelAmount", "US gal") // => gal(US)
mapUnit("fuelAmount", 3) // => gal(US)
mapUnit("distance", "kilometre") // => km
  
//now you can use the switch statement safely without the need 
//to repeat the combinations every time you call the switch
var foo = 'monthly'
switch (mapUnit ('timePeriod', foo)) {
  case 'month': 
    console.log('month')
    break
  case 'twoMonths': 
    console.log('twoMonths')
    break
  case 'trimester': 
    console.log('trimester')
    break
  case 'semester': 
    console.log('semester')
    break
  case 'year': 
    console.log('year')
    break
  default:
    throw Error('error')
}


1

Puoi farlo:

alert([
  "afshin", 
  "saeed", 
  "larry",
  "sasha",
  "boby",
  "jhon",
  "anna",
  // ...
].includes(varName)? 'Hey' : 'Default case')

o solo una singola riga di codice:

alert(["afshin", "saeed", "larry",...].includes(varName)? 'Hey' : 'Default case')

un piccolo miglioramento rispetto alla risposta di ErikE


1

Per chiunque venisse qui con un problema simile che ho avuto, che ho incontrato dopo settimane di programmazione e un esaurimento, la mia situazione era simile a:

switch (text) {
  case SOME_CONSTANT || ANOTHER_CONSTANT:
    console.log('Case 1 entered');

  break;

  case THIRD_CONSTANT || FINAL_CONSTANT:
    console.log('Case 2 entered');

  break;

  default:
    console.log('Default entered');
}

Sempre il defaultcaso è entrato. Se stai riscontrando un problema con un'istruzione switch multi-case simile, quello che stai cercando è:

switch (text) {
  case SOME_CONSTANT:
  case ANOTHER_CONSTANT:
    console.log('Case 1 entered');

  break;

  case THIRD_CONSTANT:
  case FINAL_CONSTANT:
    console.log('Case 2 entered');

  break;

  default:
    console.log('Default entered');
}

Spero che questo aiuti qualcuno, stavo strappando i capelli prima di ricordarmi di usare la custodia dell'interruttore nello stesso modo in cui lo uso nei miei riduttori di redux.


0

Una delle possibili soluzioni è:

const names = {
afshin: 'afshin',
saeed: 'saeed',
larry: 'larry'
};

switch (varName) {
   case names[varName]: {
       alert('Hey');
       break;
   }

   default: {
       alert('Default case');
       break;
   }
}

D: quale #ecma è questo?
— BG Bruno,

Ciao. Questo è ES6
— Jackkobec il

0

Per me questo è il modo più semplice:

switch (["afshin","saeed","larry"].includes(varName) ? 1 : 2) {
   case 1: 
       alert('Hey');
       break;

   default: 
       alert('Default case');
       break;
}

-1

Un altro modo di eseguire più casi nell'istruzione switch, quando all'interno di una funzione

function name(varName){
  switch (varName) {
     case 'afshin':
     case 'saeed':
     case 'larry':
       return 'Hey';
     default:
       return 'Default case';
   }
}
        
console.log(name('afshin')); //Hey


-2

Puoi scriverlo in questo modo:

switch (varName)
{
   case "afshin": 
   case "saeed": 
   case "larry": 
       alert('Hey');
       break;

   default: 
       alert('Default case');
       break;
}         

6
Questa è la stessa risposta di tutti gli altri, risolverò il "che hai dimenticato, ma pensa a cancellarlo.
— Gaunt

-3
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Example1</title>
    <link rel="stylesheet" href="css/style.css" >
    <script src="js/jquery-1.11.3.min.js" type="text/javascript"></script>
    <script>
        function display_case(){
            var num =   document.getElementById('number').value;

                switch(num){

                    case (num = "1"):
                    document.getElementById("result").innerHTML = "You select day Sunday";
                    break;

                    case (num = "2"):
                    document.getElementById("result").innerHTML = "You select day  Monday";
                    break;

                    case (num = "3"):
                    document.getElementById("result").innerHTML = "You select day  Tuesday";
                    break;

                    case (num = "4"):
                    document.getElementById("result").innerHTML = "You select day  Wednesday";
                    break;

                    case (num = "5"):
                    document.getElementById("result").innerHTML = "You select day  Thusday";
                    break;

                    case (num = "6"):
                    document.getElementById("result").innerHTML = "You select day  Friday";
                    break;

                    case (num = "7"):
                    document.getElementById("result").innerHTML = "You select day  Saturday";
                    break;

                    default:
                    document.getElementById("result").innerHTML = "You select day  Invalid Weekday";
                    break
                }

        }
    </script>
</head>
<body>
    <center>
        <div id="error"></div>
        <center>
            <h2> Switch Case Example </h2>
            <p>Enter a Number Between 1 to 7</p>
            <input type="text" id="number" />
            <button onclick="display_case();">Check</button><br />
            <div id="result"><b></b></div>
        </center>
    </center>
</body>

3
inclusione jquery classica :)
— ptim

4
Non è così switchche dovrebbe funzionare la dichiarazione. È solo case "1":, no case (num = "1"):.
— user4642212

Perché non inserire il valore del giorno all'interno del case e document.getElementById("result").innerHTML = ....all'esterno dell'interruttore e aggiungere il risultato del valore del giorno alla fine?
— Steffo Dimfelt,

@Xufox Adoro il modo in cui sovrascrive letteralmente numma funziona ancora perché switchè già stato valutato e l'assegnazione restituisce il valore. Questa è la programmazione per mutazione / machine learning al suo meglio.
— Mihail Malostanidis,

-3

basta cambiare l'interruttore di stato dell'interruttore

switch (true) {
    case (function(){ return true; })():
        alert('true');
        break;
    case (function(){ return false; })():
        alert('false');
        break;
    default:
        alert('default');
}

2
Se si inserisce true come espressione switch, nelle istruzioni "case" è possibile valutare ciò che si desidera purché si restituisca un valore booleano
— Stefano Favero,

1
Penso che intendesse dire che puoi inserire un'espressione all'interno della funzione, che valuterà e restituirà un valore dinamico per il caso, consentendo così ogni sorta di condizioni complesse
— Z. Khullah,

Per questa nota @StefanoFavero in realtà non hai bisogno di una funzione, solo (expression)tra parentesi e il valore restituito deve essere l'input. Vedi la mia risposta
— Z. Khullah,

perché l'hai sfuggito ?? Sostengo questa soluzione perché offre una flessibilità per condizioni complesse. Anche se non ti piacciono le funzioni come condizioni, puoi sostituirle con più condizioni comeswitch(true) { case (var1 === 0 && var2 === true): {} }
— AlexNikonov
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.