Switch instruction plusieurs cas en JavaScript


768

J'ai besoin de plusieurs cas dans l'instruction switch en JavaScript, quelque chose comme:

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

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

Comment puis je faire ça? S'il n'y a aucun moyen de faire quelque chose comme ça en JavaScript, je veux connaître une solution alternative qui suit également le concept DRY .


5
À celui qui a voté pour clore cette question. Il a plus de 5 ans et a une réponse acceptée - pourquoi le vote serré?
surfmuggle

@surfmuggle car il n'est pas nécessaire d'ajouter plus de réponses.
Afshin Mehrabani

7
@AfshinMehrabani peut-être peut-il être protégé, pas fermé?
evolutionxbox

Réponses:


1511

Utilisez la fonction fall-through de l' switchinstruction. Un cas correspondant s'exécutera jusqu'à ce qu'un break(ou la fin de l' switchinstruction) soit trouvé, vous pouvez donc l'écrire comme suit:

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

   default: 
       alert('Default case');
}


2
D'une certaine manière, cela fonctionne pour moi dans Chrome, dans la console javascript: switch('10') { case 1, '10': console.log('ok') }imprimeok
nafg

8
@nafg: Essayez switch(1). L'étiquette ici n'est qu'une expression virgule.
kennytm

4
@Barney Non, sans la pause, vous pouvez passer au cas suivant.
Seiyria

1
@Seiyira par définition, il n'y a pas de cas suivant après le dernier. En plus, c'est un défaut.
Barney le

101

Cela fonctionne en JavaScript standard

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

À votre santé.


13
@believesInSanta c'est littéralement juste un cas normal avec une mise en forme bizarre (des espaces au lieu de nouvelles lignes)
Mihail Malostanidis

42

Voici une approche différente en évitant switchcomplètement la déclaration:

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

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

5
Je préfère définitivement cette version. Fall through est une fonctionnalité sujette aux bogues de switch ... case. Il est trop facile d'oublier une breakdéclaration, et si vous utilisez intentionnellement une erreur, ces breakdéclarations oubliées peuvent être très difficiles à repérer. Cette version de recherche de méthode possède également de nombreuses fonctionnalités intéressantes switch ... case, telles que l'extensibilité dynamique ou la possibilité de remplacer complètement l'objet pour effectuer le changement de mode. Il est également plus facile de rester organisé correctement et peut conduire à un code plus facile à gérer. Voir ericleads.com/2012/12/switch-case-considered-harmful
Eric Elliott

31
J'ajoute toujours un commentaire //fallthroughà la place de breakchaque fois que j'omet intentionnellement le break. Cela permet d'identifier quand c'est une erreur et quand c'est intentionnel.
Mnebuerquo

18
Approche intuitive. Cependant, pour plus de lisibilité, je recommanderais d'utiliser l'instruction native switch.
contactmatt

39
On peut toujours se gratter l'oreille gauche en passant sa main droite par l'arrière du cou ... (désolé pour mon anglais, je veux dire: "on peut toujours compliquer les choses autant que possible ... dans ce cas, en évitant le switch switch en faveur de cette solution compliquée ne semble pas être la bonne chose à faire ...)
Clint Eastwood

25
Je suis vraiment étonné de voir comment cela a obtenu 34 votes. En termes de lisibilité et de maintenabilité, c'est absolument horrible. Si je veux voir quelles conditions déclencheront quelque chose, une déclaration de cas est incroyablement simple et facile à voir en regardant les étiquettes. D'un autre côté, votre version nécessiterait que quelqu'un lise à peu près toutes les lignes et voit ce que vous avez attribué où. Cela s'aggrave également avec le nombre de cas que vous souhaitez faire correspondre.
michael

21

En Javascript pour attribuer plusieurs cas dans un commutateur, nous devons définir different case without break inbetweencomme indiqué ci-dessous:

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

S'il vous plaît voir l'exemple cliquez sur le lien


5
C'est une technique courante dans une multitude de langages, non liée à JS
drAlberT

13

Si vous utilisez ES6, vous pouvez le faire:

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

Ou pour les versions antérieures de JavaScript, vous pouvez le faire:

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

Notez que cela ne fonctionnera pas dans les anciens navigateurs IE, mais vous pouvez corriger les choses assez facilement. Voir la question déterminer si la chaîne est dans la liste en javascript pour plus d'informations.


Quel est l'avantage de cela sur un commutateur?
Bryce Snyder

@BryceSnyder la différence entre une expression et une déclaration? Moins de frappe? Moins de lignes verticales consommées? Plus de puissance expressive par la concision et la densité de représentation? Une meilleure sémantique grâce au includesmot? Faites votre choix.
ErikE

7

Dans le nœud, il semble que vous êtes autorisé à le faire:

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

Cela rend le code beaucoup plus compact dans certains cas.


1
Je pense que la syntaxe est la même que pour les autres environnements JS.
Afshin Mehrabani

1
@AfshinMehrabani Il se pourrait, je ne l'ai testé que dans le contexte nodejs.
Automatico

Oui. J'aime économiser de l'espace vertical!
Channel

7

En ajoutant et en clarifiant la réponse de Stefano, vous pouvez utiliser des expressions pour définir de manière dynamique les valeurs des conditions dans switch, par exemple:

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

Donc, dans votre problème, vous pourriez faire quelque chose comme:

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

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

bien que n'étant pas tellement SEC ..


pas encore testé mais il serait intéressant de modifier l' varNameintérieur de l'expression case, attendez-vous à ce que varName soit mis en cache.
Valen

5

vous pouvez utiliser l' opérateur ' in ' ...
repose sur l'invocation objet / hachage ...
donc c'est aussi rapide que javascript peut être ...

// 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]()

Profitez-en, ZEE


comment cela se rapporte-t-il au changement? pouvez-vous le clarifier?
Z. Khullah

pourquoi voudriez-vous rendre votre code "difficile à lire". La première chose que l'on m'a dit en tant que programmeur était d'écrire du code avec la mentalité que la prochaine personne qui lit votre code est un tueur en série brandissant une hache et qu'il déteste ne pas pouvoir comprendre le code.
MattE

Salut Matt ... Je le présente ici comme une preuve de concept ... de toute façon ce formulaire vous offre plus de fonctionnalité et de flexibilité ... et vous ne l'utilisez que si vous le souhaitez ... ou si vous trouvez une contrainte dans votre forme habituelle de faire les choses ... considérez ir comme un outil de plus dans la boîte à outils de votre programmeur ...
ZEE

5

J'utilise comme ça:

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

Vous n'avez pas besoin d'utiliser le gdrapeau, car vous n'utilisez les expressions régulières qu'une seule fois et vous les jetez. En fait, si vous les gardiez en dehors de la fonction, l' gindicateur vous nuirait en essayant de faire une correspondance à partir d'un index non 0 sur les .test(s suivants . J'ai également corrigé une faute de frappe où la casse du commutateur était sensorvariable et non trueconstante pour faire correspondre les expressions booléennes. Voir l'édition.
Mihail Malostanidis

J'ai utilisé ce format pour tester des types de fichiers. Ex:case /officedocument/.test(type) && /presentation/.test(type): iconClass = "far fa-file-powerpoint red"; break;
tbone849

4

Ça dépend. Switch n'évalue qu'une seule fois. Lors d'un match, toutes les déclarations de cas ultérieures jusqu'à ce que «casser» se déclenchent, peu importe ce que dit le cas.

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

J'aime cela pour la clarté et la syntaxe DRY.

varName = "larry";

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

    default: 
       alert('Default case');

}

2

Je peux voir qu'il y a beaucoup de bonnes réponses ici, mais que se passe-t-il si nous devons vérifier plus de 10 cas? Voici ma propre approche:

 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
C'est un abus de la déclaration switch. C'est if (accessDenied.includes(varName)) return 'Access Denied!'; return 'Access Allowed.'plus que suffisant.
Mihail Malostanidis

2

Le problème avec les approches ci-dessus est que vous devez répéter plusieurs casefois chaque fois que vous appelez la fonction qui a le switch. Une solution plus robuste consiste à avoir une carte ou un dictionnaire .

Voici un exemple

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

Tu peux le faire:

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

ou juste une seule ligne de code:

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

une petite amélioration de la réponse d'ErikE


1

Pour tous ceux qui viennent ici avec un problème similaire que j'ai eu, que j'ai rencontré après des semaines de codage et un burn-out, ma situation ressemblait à:

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

Toujours le defaultcas entré. Si vous rencontrez un problème d'instruction de commutateur multi-cas similaire, ce que vous recherchez est:

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

J'espère que cela aide quelqu'un, je tirais mes cheveux avant de me rappeler d'utiliser le boîtier de commutation de la même manière que je l'utilise dans mes réducteurs redux.


0

Une des solutions possibles est:

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

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

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

Q pls quel #ecma est-ce?
BG Bruno

Salut. Ceci est ES6
Jackkobec

0

Pour moi, c'est la manière la plus simple:

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

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

-1

Une autre façon de faire plusieurs cas dans une instruction switch, à l'intérieur d'une fonction

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


-2

Vous pouvez l'écrire comme ceci:

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

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

6
C'est la même réponse que tout le monde, je vais corriger le "que vous avez oublié, mais pensez à le supprimer.
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
inclusion jquery classique :)
ptim

4
Ce n'est pas ainsi que la switchdéclaration est censée fonctionner. C'est juste case "1":, non case (num = "1"):.
user4642212

Pourquoi ne pas mettre la valeur du jour à l'intérieur du boîtier et document.getElementById("result").innerHTML = ....à l'extérieur du commutateur et ajouter le résultat de la valeur du jour à la fin?
Steffo Dimfelt du

@Xufox J'adore la façon dont il écrase littéralement, nummais cela fonctionne toujours car le switcha déjà été évalué et l'affectation donne la valeur. C'est la programmation par mutation / apprentissage automatique à son meilleur.
Mihail Malostanidis

-3

il suffit de changer l'approche de la condition de commutation

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

2
Si vous définissez true comme expression de commutateur, dans la ou les instructions "case", vous pouvez évaluer tout ce que vous voulez à condition de renvoyer un booléen
Stefano Favero

1
Je pense que ce qu'il voulait dire, c'est que vous pouvez mettre une expression à l'intérieur de la fonction, qui évaluera et retournera une valeur dynamique pour le cas, permettant ainsi toutes sortes de conditions complexes
Z. Khullah

Pour cette note @StefanoFavero, vous n'avez pas réellement besoin d'une fonction, juste (expression)entre parenthèses, et la valeur de retour doit être l'entrée. Voir ma réponse
Z. Khullah

pourquoi vous l'avez utilisé ?? Je préconise cette solution car elle offre une flexibilité pour des conditions complexes. Même si vous n'aimez pas les fonctions comme conditions, vous pouvez les remplacer par plusieurs conditions telles queswitch(true) { case (var1 === 0 && var2 === true): {} }
AlexNikonov
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.