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.