3 septembre 2023

La déclaration "switch"

Une instruction switch peut remplacer plusieurs vérification if.

Cela donne un moyen plus descriptif de comparer une valeur avec plusieurs variantes.

La syntaxe

Le switch a un ou plusieurs blocs case (cas) et une valeur par défaut facultative.

Cela ressemble à ceci :

switch(x) {
  case 'value1':  // si (x === 'value1')
    ...
    [break]

  case 'value2':  // si (x === 'value2')
    ...
    [break]

  default:
    ...
    [break]
}
  • La valeur de x est vérifiée pour une égalité stricte avec la valeur du premier case (c’est-à-dire, value1), puis du second (value2) et ainsi de suite.
  • Si l’égalité est trouvée, switch commence à exécuter le code à partir du case correspondant, jusqu’au prochain break (ou jusqu’à la fin du switch).
  • Si aucun cas ne correspond, le code par défaut (default) est exécuté (s’il existe).

Un exemple

Un exemple de switch (le code exécuté est mis en évidence) :

let a = 2 + 2;

switch (a) {
  case 3:
    alert( 'Too small' );
    break;
  case 4:
    alert( 'Exactly!' );
    break;
  case 5:
    alert( 'Too big' );
    break;
  default:
    alert( "I don't know such values" );
}

Ici, le switch commence à comparer a avec le premier case dont la valeur est 3. La correspondance échoue.

Ensuite 4, c’est une correspondance. L’exécution commence donc à partir du case 4 jusqu’au prochain break.

S’il n’y a pas de break, l’exécution continue avec le case suivant sans aucun contrôle.

Un exemple sans break:

let a = 2 + 2;

switch (a) {
  case 3:
    alert( 'Too small' );
  case 4:
    alert( 'Exactly!' );
  case 5:
    alert( 'Too big' );
  default:
    alert( "I don't know such values" );
}

Dans l’exemple ci-dessus, nous verrons l’exécution séquentielle de trois alert :

alert( 'Exactly!' );
alert( 'Too big' );
alert( "I don't know such values" );
Toute expression peut être un argument switch/case

Switch et case permettent des expressions arbitraires.

Par exemple :

let a = "1";
let b = 0;

switch (+a) {
  case b + 1:
    alert("this runs, because +a is 1, exactly equals b+1");
    break;

  default:
    alert("this doesn't run");
}

Ici +a donne 1, qui est comparé à b + 1 dans le case, et le code correspondant est exécuté.

Groupement de “case”

Plusieurs variantes de case partageant le même code peuvent être regroupées.

Par exemple, si nous voulons que le même code soit exécuté pour les case 3 et case 5 :

let a = 2 + 2;

switch (a) {
  case 4:
    alert('Right!');
    break;

  case 3: // (*) grouped two cases
  case 5:
    alert('Wrong!');
    alert("Why don't you take a math class?");
    break;

  default:
    alert('The result is strange. Really.');
}

Maintenant, les 3 et 5 affichent le même message.

La possibilité de “grouper” les case est un effet secondaire de la façon dont le switch/case fonctionne sans break. Ici, l’exécution du case 3 commence à partir de la ligne (*) et passe par le case 5, car il n’y a pas de break.

Le type compte

Soulignons que le contrôle d’égalité est toujours strict. Les valeurs doivent être du même type pour correspondre.

Par exemple, considérons le code suivant :

let arg = prompt("Enter a value?");

switch (arg) {
  case '0':
  case '1':
    alert( 'One or zero' );
    break;

  case '2':
    alert( 'Two' );
    break;

  case 3:
    alert( 'Never executes!' );
    break;

  default:
    alert( 'An unknown value' );
}
  1. Pour 0, 1, la première alert est exécutée.
  2. Pour 2, la deuxième alert est exécutée.
  3. Mais pour 3, le résultat du prompt est une chaîne de caractères "3", ce qui n’est pas strictement égal === au chiffre 3. Nous avons donc un code mort dans le case 3 ! La variante par défaut sera donc exécutée.

Exercices

importance: 5

Écrivez le code en utilisant if..else qui correspondrait au switch suivant :

switch (browser) {
  case 'Edge':
    alert( "You've got the Edge!" );
    break;

  case 'Chrome':
  case 'Firefox':
  case 'Safari':
  case 'Opera':
    alert( 'Okay we support these browsers too' );
    break;

  default:
    alert( 'We hope that this page looks ok!' );
}

Pour correspondre précisément à la fonctionnalité du switch, le if doit utiliser une comparaison stricte '==='.

Cependant, pour des chaînes de caractères données, un simple '==' fonctionne également.

if(browser == 'Edge') {
  alert("You've got the Edge!");
} else if (browser == 'Chrome'
 || browser == 'Firefox'
 || browser == 'Safari'
 || browser == 'Opera') {
  alert( 'Okay we support these browsers too' );
} else {
  alert( 'We hope that this page looks ok!' );
}

Remarque: la construction browser == 'Chrome' || navigateur == 'Firefox'… est divisée en plusieurs lignes pour une meilleure lisibilité.

Mais la construction switch est toujours plus propre et plus descriptive.

importance: 4

Réécrivez le code ci-dessous en utilisant une seule instruction switch :

let a = +prompt('a?', '');

if (a == 0) {
  alert( 0 );
}
if (a == 1) {
  alert( 1 );
}

if (a == 2 || a == 3) {
  alert( '2,3' );
}

Les deux premiers contrôles se transforment en deux case. Le troisième contrôle est divisé en deux case :

let a = +prompt('a?', '');

switch (a) {
  case 0:
    alert( 0 );
    break;

  case 1:
    alert( 1 );
    break;

  case 2:
  case 3:
    alert( '2,3' );
    break;
}

Remarque: le break en bas n’est pas requis. Mais nous le mettons pour rendre le code à l’épreuve du temps.

Dans le futur, il est possible que nous voulions ajouter un case supplémentaire, par exemple le case 4. Et si nous oublions d’ajouter un break avant, à la fin du case 3, il y aura une erreur. C’est donc une sorte d’assurance.

Carte du tutoriel

Commentaires

lire ceci avant de commenter…
  • Si vous avez des améliorations à suggérer, merci de soumettre une issue GitHub ou une pull request au lieu de commenter.
  • Si vous ne comprenez pas quelque chose dans l'article, merci de préciser.
  • Pour insérer quelques bouts de code, utilisez la balise <code>, pour plusieurs lignes – enveloppez-les avec la balise <pre>, pour plus de 10 lignes - utilisez une sandbox (plnkr, jsbin, codepen…)