Programmation JavaScript/Structures de contrôle
JavaScript dispose de structures de contrôle comparables à ce qu'on rencontre en langage C. La plupart des règles et habitudes acquises dans ce langage sont immédiatement transposables en JavaScript.
Avant de passer en revue les structures de contrôle, il est utile de lire le paragraphe Établissement d'une expression logique qui précise certains aspects de la méthode.
Établissement d'une expression logique
L'usage de if, while et do met en œuvre des expressions logiques dont le résultat testé (vrai) conditionnera l'exécution de l'instruction ou du bloc d'instructions associé.
Ces expressions logiques sont inscrites entre parenthèses.
Du plus simple au plus complexe, on trouve :
- (5 == 5) est bizarre mais vrai
- (true) La constante true est toujours vraie
- (false) La constante false est toujours fausse
- (var_bool) Si var_bool est vrai, l'expression est vraie
- (!var_bool)Si var_bool est vrai, l'expression est fausse
- (var_bool==false) Si var_bool est faux, l'expression est vraie (et oui...)
Avec des variables numériques ou des variables chaînes, le principe est similaire :
- (ma_var_num == 5)
- (ma_chaine == "foo")
De même avec les opérateurs de comparaison :
- (ma_var > 0) ma_var non nulle
- (ma_var <= 5) inférieure ou égale à 5
- (ma_chaine != "bar") le contenu de ma_chaine différent de "bar"
etc..
À l'étape suivante, on peut combiner des expressions logiques avec des opérateurs logiques ET ( && ) et OU (||).
- ((ma_var==5)&&(ma_chaine=="bar")) Réaliser les deux conditions
- ((ma_var==5)||(ma_chaîne=="bar")) Réaliser l'une des conditions
- ((ma_var==5)&&(ma_chaine=="bar")||(!var_bool))
... Et ainsi de suite... en faisant très attention aux parenthèses et à l'ordre de priorité des opérateurs, et à conserver une certaine lisibilité au code.
Le piège
L'auteur de cet article ne vient pas du C , mais du pascal. Il commet donc encore aujourd'hui l'erreur de confondre l'opérateur d'affectation avec l'opérateur d'égalité logique. Ceci a pour conséquence d'introduire un bug à retardement dû à l'affectation de la variable de test.
if (ma_var = 0) Exécution du code
L'expression (ma_var = 0) est fausse. L'expression (ma_var = 5) est vraie. Mais dans les deux cas, l'affectation a lieu, écrasant le contenu précédent de la variable.
Donc cette erreur, si elle n'est pas comprise, plonge le programmeur dans des abîmes de questions et de doutes, avec peu de chances de comprendre pourquoi. Bien entendu, la bonne façon est d'utiliser l'opérateur d'égalité logique ( == ) à la place de l'opérateur d'affectation ( = ).
La valeur de l'opération d'affectation peut cependant être utilisée volontairement. Voir la section sur l'opérateur =.
Branchement conditionnel
if else
La structure de contrôle if permet de subordonner l'exécution d'une ligne ou d'un bloc d'instructions à l'évaluation (vrai) d'une expression logique.
La syntaxe est :
if (condition_vrai) // Exécution d'une ligne d'instructions
alert("La condition est vraie");
.
.
.
if (condition_vrai) // Exécution d'un bloc d'instructions
{
alert("La condition est vrai");
alert("... je le confirme");
}
Le mot réservé else permet d'exécuter une ligne ou un bloc d'instructions alternativement au résultat de l'évaluation de l'expression logique.
if (condition)
alert("La condition est vrai");
else
alert("la condition est fausse");
.
.
.
if (condition)
{
alert("La condition est vraie");
alert("... je le confirme");
}
else
{
alert("la condition est fausse");
alert("... je le confirme");
}
? :
Cet opérateur est remarquable par sa concision et peut se substituer à la structure if… else. Il est expliqué en détails sur la page précédente.
Parfois, il permet d'économiser beaucoup de code. En théorie, presque toute structure if... else peut être remplacée par cet opérateur, du moment qu'elle ne contient pas de déclaration. En pratique, il vaut mieux le réserver à des cas simples.
switch
Le mot réservé switch permet en conjonction avec case de mettre en place un sélecteur de cas d'une grande souplesse.
Cette structure remplace avantageusement une structure équivalente construite à partir de if else et if else imbriqués.
Le mécanisme de test ne fait pas appel à une expression logique, mais à une comparaison d'une variable de type scalaire avec des valeurs du même type.
Contrairement au langage C, qui nécessite que les valeurs de comparaison soient des constantes littérales, JavaScript, interprété, autorise l'usage de variables.
La structure switch case ne pourrait pas fonctionner correctement sans break.
En effet, et cela est déconcertant au début, quand une condition case est vérifiée, l'interpréteur n'effectue plus de test et exécute tout ce qu'il trouve jusqu'à la fin en passant par dessus les case rencontrés.
Enfin, le mot réservé default couvre les cas différents de ceux traités par les case.
switch(ma_var)
{
var egal_deux = 2
case 1 :
alert("Ma variable vaut 1");
break;
case egal_deux :
alert("Ma variable vaut 2");
break;
default : alert("Ma variable vaut autre chose que 1 ou 2");
}
On remarque les break systématiques dans ce cas.
D'autre part, on illustre la possibilité de fournir des variables à case, ce qui n'est pas possible en langage C.
Deuxième exemple : Nous allons regrouper plusieurs cas, et déclencher plusieurs exécutions d'instructions pour certaines valeurs.
switch(ma_var)
{
case 0:
alert("Vraiment nulle, cette variable"); // Elle vaut zero
break;
case 1:
case 3: alert("Ma variable vaut 1 ou 3"); // Et on continue
case 5:
alert("Ma variable est impaire et comprise entre 1 et 5");
break;
case 2:
case 4:
case 6:
alert("Ma variable est paire et comprise entre 2 et 6");
break;
case 7:
alert("Ma variable est égale à 7");
break;
default: alert("Ma variable est négative ou supérieure à 7")
}
On remarquera l'utilisation des break pour regrouper des cas entre eux...
Contrôle d'itération (boucles)
JavaScript implémente les mêmes structures de contrôle d'itération que le langage c, à savoir les boucles for, while et do.
Avant de les examiner, nous allons regarder l'usage de continue et break appliqué aux boucles.
Utilisation de continue
Cette instruction permet à volonté de sauter des tours. L'exemple suivant saute le passage à zero d'une itération comprise entre -2 et 2.
for (var i=-2; i <= 2; i++)
{
if (i==0)
continue;
alert(i); // Affiche -2, puis -1, 1 et 2... mais pas le zero.
}
Cette fonctionnalité de continue est aussi applicable aux boucles while et do.
continue
peut être suivi du nom d'une étiquette placée juste avant une boucle. Dans ce cas, l'exécution continue au niveau de cette boucle, pas de celle qui contient directement l'instruction continue
.
Utilisation de break
Les boucle for, while et do autorisent l'usage de break pour sortir de l'itération.
Chacune de ces boucles possède une condition d'arrêt, mais parfois il peut être souhaitable de sortir de la boucle pour d'autres raisons (en cas d'erreur, si on a trouvé ce qu'on cherchait avant la fin d'une recherche, si l'utilisateur a décidé d'annuler une longue opération…).
Par défaut, break
termine immédiatement la boucle dont il fait partie et le script continue après cette boucle.
De même que continue
, break
peut être suivi du nom d'une étiquette. Dans ce cas, l'exécution continue après la structure désignée par l'étiquette, pas après la boucle qui contient directement l'instruction break
.
Quand on utilise la boucle .each(), elle exécute une fonction, donc il faut remplacer "break" par "return false".
Exemple pour sélectionner une option d'un menu déroulant :
$(document).ready(function(){
$("#liste_deroulante > option").each(function() {
if ($(this).val() == "valeur à sélectionner") {
$(this).attr('selected','selected');
return false;
}
});
});
Étiquettes
Une étiquette est un identifiant suivi de ':' (deux points). On peut la placer avant une instruction ou une structure de contrôle.
Il n'y a pas d'instruction goto
en JavaScript. Les étiquettes servent exclusivement à affiner l'utilisation de break
et continue
(voir plus haut).
str = "Liste des objets :\n"
annuler = false
parcoursListe : for(i in liste)
{
if(!liste.hasOwnProperty(i))
continue // passe à l'itération suivante dans cette boucle
str+="\n• L'élément «"+i+"» de la liste contient :\n"
if(annuler)
{
str+="\nopération annulée."
break // reprend l'exécution immédiatement après cette boucle
}
parcoursProps : for(j in liste[i])
{
if(!liste[i].hasOwnProperty(j))
continue // passe à l'itération suivante dans cette boucle
if(annuler)
{
str+="\nopération annulée."
break parcoursListe // reprend l'exécution immédiatement après la boucle extérieure
}
str+="- "+j+" = "+liste[i][j]+"\n"
}
}
for
Description
La structure for permet d'effectuer plusieurs fois une ligne d'instructions ou un bloc d'instructions.
Les modalités d'exécution de l'itération sont indiquées entre les parenthèses précédant le mot réservé for. L'instruction ou le bloc à exécuter se situent après.
Syntaxe:
for (modalités) action;
ou
for (modalités){action1; action2;}
Par modalités, nous regroupons en fait trois choses distinctes qui sont:
- l'initialisation
- La condition pour exécuter la boucle
- Les changements à effectuer à chaque tour (généralement une incrémentation ou décrémentation).
Ces trois instructions sont séparées par des points-virgule et placées entre parenthèses après le mot réservé for.
Généralement, ces trois instructions s'appliquent à une variable chargée de contrôler l'itération, et qu'on nomme avec la lettre i.
Boucle croissante
L'exemple le plus simple est le suivant :
for (i = 0; i < 5; i++)
{
alert(i); // Affiche 0, puis 1, puis 2, puis 3, puis 4
}
Dans cet exemple, nous avons initialisé la variable i à 0, défini la condition pour exécuter la boucle (répéter tant que i est strictement inférieur à 5) et défini le changement à effectuer à chaque tour (incrémenter i).
Une fois assimilé le fonctionnement, on imagine aisément toutes les possibilités.
D'abord, on peut initialiser i avec la valeur de son choix. Commencer avec 1, ou un nombre négatif.
Ensuite, on est libre de l'expression de la condition : strictement inférieur à 5, inférieur ou égal à 5 (<=) à condition devienne fausse à un moment donné, pour sortir.
Boucle à paliers
On n'est pas tenu exclusivement d'incrémenter i. On peut modifier la valeur par pas de 2.
for (i = 4; i <= 10; i += 2)
alert(i + "est un nombre pair compris entre 4 et 10); // affiche 4, puis 6, 8 et 10
Boucle décroissante
De la même manière, une boucle peut être décroissante :
for (i = 5; i >= 0; i--)
alert(i); // affiche 5, puis 4, 3, 2, 1 et 0
État en sortie de boucle
En sortie de boucle, i contient la valeur résultante des modifications. Pour le dernier exemple, c'est -1.
Boucle de parcours
Grâce à l'opérateur in
il est possible d'utiliser une forme spéciale de la boucle for
pour parcourir un tableau ou une table associative (clé -> valeur) par ses indices/clés :
var tableau = [ "une", "boucle for", "spéciale" ];
for (var i in tableau)
alert(tableau[i]); // affiche successivement tous les éléments du tableau
// i valant successivement : 0, 1, 2
var table = { "yes":"oui" , "no":"non" , "maybe":"peut-être" };
for (var i in table)
alert(table[i]); // affiche successivement "oui", "non", "peut-être"
// i valant successivement : "yes", "no", "maybe"
Éviter les pièges :
Boucle infinie
Il est possible, par inattention, de programmer une boucle infinie. Cela se produit quand la condition de boucle reste vraie malgré la modification de la variable.
for (i=0; i >= 0; i++)
L'incrémentation de i ne changera pas le fait que la variable est supérieure ou égale à zéro...
Variable modifiée
La structure for s'appuie sur une variable pour piloter le déroulement de la boucle. Seulement, elle ne rend pas la variable comme elle l'a reçue. Elle la modifie complètement. Pour éviter de modifier une variable par erreur, il est judicieux d'utiliser le mot réservé var
pour déclarer une variable locale à la boucle :
for (var i=0; ....
while
La structure while conditionne l'exécution répétée d'une instruction ou d'un bloc d'instructions au test d'une expression logique.
while (condition)
action;
ou
while (condition)
{
action1;
action2;
}
Pour qu'il soit possible de sortir de la boucle, il faut que les instructions modifient à terme la condition pour la rendre fausse.
var i = 0; // Initialiser i
while (i<5) // Tant que i est strictement inférieur à cinq
i++; // ... l'incrémenter.
En langage c, la boucle while peut-être volontairement infinie : while(true) toujours vrai, mais en JavaScript, le navigateur ne l'acceptera probablement pas.
do
La structure do permet d'exécuter une instruction ou un bloc d'instructions et de répéter cette action tant qu'une expression logique surveillée par while est vraie.
do
action
while (condition)
var i = 0;
do
{
i++
}
while(i < 5);