Les boucles

Les programmeurs sont réputés pour être des gens fainéants, ce qui n'est pas totalement faux puisque le but de la programmation est de faire exécuter des choses à un ordinateur, pour ne pas les faire nous-mêmes. Ce chapitre va mettre en lumière ce comportement intéressant : nous allons en effet voir comment répéter des actions, pour ne pas écrire plusieurs fois les mêmes instructions. Mais avant ça, nous allons aborder le sujet de l'incrémentation.

L'incrémentation

Considérons le calcul suivant :

var number = 0;
number = number + 1;

La variablenumbercontient donc la valeur 1. Seulement l'instruction pour ajouter 1 est assez lourde à écrire et souvenez-vous, nous sommes des fainéants. Le JavaScript, comme d'autres langages de programmation, permet ce que l'on appelle l'incrémentation, ainsi que son contraire, la décrémentation.

Le fonctionnement

L'incrémentation permet d'ajouter une unité à un nombre au moyen d'une syntaxe courte. À l'inverse, la décrémentation permet de soustraire une unité.

var number = 0;
number++;
alert(number); // Affiche : « 1 »
number--;
alert(number); // Affiche : « 0 »

Il s'agit donc d'une méthode assez rapide pour ajouter ou soustraire une unité à une variable (on dit incrémenter et décrémenter), et cela nous sera particulièrement utile tout au long de ce chapitre.

L'ordre des opérateurs

Il existe deux manières d'utiliser l'incrémentation en fonction de la position de l'opérateur ++ (ou --). On a vu qu'il pouvait se placer après la variable, mais il peut aussi se placer avant. Petit exemple :

var number_1 = 0;
var number_2 = 0;
number_1++;
++number_2;
alert(number_1); // Affiche : « 1 »
alert(number_2); // Affiche : « 1 »

number_1etnumber_2ont tous deux été incrémentés. Quelle est donc la différence entre les deux procédés ?

La différence réside en fait dans la priorité de l'opération, et ça a de l'importance si vous voulez récupérer le résultat de l'incrémentation. Dans l'exemple suivant,++numberretourne la valeur denumberincrémentée, c'est-à-dire 1.

var number = 0;
var output = ++number;
alert(number); // Affiche : « 1 »
alert(output); // Affiche : « 1 »

Maintenant, si on place l'opérateur après la variable à incrémenter, l'opération retourne la valeur denumberavant qu'elle ne soit incrémentée :

var number = 0;
var output = number++;
alert(number); // Affiche : « 1 »
alert(output); // Affiche : « 0 »

Ici donc, l'opérationnumber++a retourné la valeur denumbernon incrémentée.

La boucle while

Une boucle est une structure analogue aux structures conditionnelles vues dans le chapitre précédent sauf qu'ici il s'agit de répéter une série d'instructions. La répétition se fait jusqu'à ce qu'on dise à la boucle de s'arrêter. À chaque fois que la boucle se répète on parle d'itération (qui est en fait un synonyme de répétition).

Fonctionnement de la boucle while
Fonctionnement de la boucle while

Pour faire fonctionner une boucle, il est nécessaire de définir une condition. Tant que celle-ci est vraie (true), la boucle se répète. Dès que la condition est fausse (false), la boucle s'arrête.

Voici un exemple de la syntaxe d'une bouclewhile:

while (condition) {
instruction_1;
instruction_2;
instruction_3;
}

Répéter tant que…

La bouclewhilese répète tant que la condition est validée. Cela veut donc dire qu'il faut s'arranger, à un moment, pour que la condition ne soit plus vraie, sinon la boucle se répéterait à l'infini, ce qui serait fâcheux.

En guise d'exemple, on va incrémenter un nombre, qui vaut 1, jusqu'à ce qu'il vaille 10 :

var number = 1;
while (number < 10) {
number++;
}
alert(number); // Affiche : « 10 »

Au départ,numbervaut 1. Arrive ensuite la boucle qui va demander sinumberest strictement plus petit que 10. Comme c'est vrai, la boucle est exécutée, etnumberest incrémenté. À chaque fois que les instructions présentes dans la boucle sont exécutées, la condition de la boucle est réévaluée pour savoir s'il faut réexécuter la boucle ou non. Dans cet exemple, la boucle se répète jusqu'à ce quenumbersoit égal à 10. Sinumbervaut 10, la conditionnumber < 10est fausse, et la boucle s'arrête. Quand la boucle s'arrête, les instructions qui suivent la boucle (la fonctionalert()dans notre exemple) sont exécutées normalement.

Exemple pratique

Imaginons un petit script qui va demander à l'internaute son prénom, ainsi que les prénoms de ses frères et sœurs. Ce n'est pas compliqué à faire direz-vous, puisqu'il s'agit d'afficher une boîte de dialogue à l'aide deprompt()pour chaque prénom. Seulement, comment savoir à l'avance le nombre de frères et sœurs ?

Nous allons utiliser une bouclewhile, qui va demander, à chaque passage dans la boucle, un prénom supplémentaire. La boucle ne s'arrêtera que lorsque l'utilisateur choisira de ne plus entrer de prénom.

var nicks = '',
nick,
proceed = true;
while (proceed) {
nick = prompt('Entrez un prénom :');
if (nick) {
nicks += nick + ' '; // Ajoute le nouveau prénom ainsi qu'une espace juste après
} else {
proceed = false; // Aucun prénom n'a été entré, donc on fait en sorte d'invalider la condition
}
}
alert(nicks); // Affiche les prénoms à la suite

Essayer le code

La variableproceedest ce qu'on appelle une variable témoin, ou bien une variable de boucle. C'est une variable qui n'intervient pas directement dans les instructions de la boucle mais qui sert juste pour tester la condition. Nous avons choisi de la nommerproceed, qui veut dire « poursuivre » en anglais.

À chaque passage dans la boucle, un prénom est demandé et sauvé temporairement dans la variablenick. On effectue alors un test surnickpour savoir si elle contient quelque chose, et dans ce cas, on ajoute le prénom à la variablenicks. Remarquez que nous ajoutons aussi un espace, pour séparer les prénoms. Si par contrenickcontient la valeurnull— ce qui veut dire que l'utilisateur n'a pas entré de prénom ou a cliqué surAnnuler— on change la valeur deproceedenfalse, ce qui invalidera la condition, et cela empêchera la boucle de refaire une itération.

Quelques améliorations

Utilisation debreak

Dans l'exemple des prénoms, nous utilisons une variable de boucle pour pouvoir arrêter la boucle. Cependant, il existe un mot-clé pour arrêter la boucle d'un seul coup. Ce mot-clé estbreak, et il s'utilise exactement comme dans la structure conditionnelleswitch, vue au chapitre précédent. Si l'on reprend l'exemple, voici ce que ça donne avec unbreak:

var nicks = '',
nick;
while (true) {
nick = prompt('Entrez un prénom :');
if (nick) {
nicks += nick + ' '; // Ajoute le nouveau prénom ainsi qu'une espace juste après
} else {
break; // On quitte la boucle
}
}
alert(nicks); // Affiche les prénoms à la suite

Essayer le code

Utilisation decontinue

Cette instruction est plus rare, car les opportunités de l'utiliser ne sont pas toujours fréquentes.continue, un peu commebreak, permet de mettre fin à une itération, mais attention, elle ne provoque pas la fin de la boucle : l'itération en cours est stoppée, et la boucle passe à l'itération suivante.

La boucle do while

La boucledo whileressemble très fortement à la bouclewhile, sauf que dans ce cas la boucle est toujours exécutée au moins une fois. Dans le cas d'une bouclewhile, si la condition n'est pas valide, la boucle n'est pas exécutée. Avecdo while, la boucle est exécutée une première fois, puis la condition est testée pour savoir si la boucle doit continuer.

Voici la syntaxe d'une boucledo while:

do {
instruction_1;
instruction_2;
instruction_3;
} while (condition);

On note donc une différence fondamentale dans l'écriture par rapport à la bouclewhile, ce qui permet de bien faire la différence entre les deux. Cela dit, l'utilisation des bouclesdo whilen'est pas très fréquente, et il est fort possible que vous n'en ayez jamais l'utilité car généralement les programmeurs utilisent une bouclewhilenormale, avec une condition qui fait que celle-ci est toujours exécutée une fois.

La boucle for

La boucleforressemble dans son fonctionnement à la bouclewhile, mais son architecture paraît compliquée au premier abord. La boucleforest en réalité une boucle qui fonctionne assez simplement, mais qui semble très complexe pour les débutants en raison de sa syntaxe. Une fois que cette boucle est maîtrisée, il y a fort à parier que c'est celle-ci que vous utiliserez le plus souvent.

Le schéma d'une boucleforest le suivant :

for (initialisation; condition; incrémentation) {
instruction_1;
instruction_2;
instruction_3;
}

Dans les parenthèses de la boucle ne se trouve plus juste la condition, mais trois blocs : initialisation, condition, et incrémentation. Ces trois blocs sont séparés par un point-virgule ; c'est un peu comme si les parenthèses contenaient trois instructions distinctes.

for, la boucle conçue pour l'incrémentation

La boucleforpossède donc trois blocs qui la définissent. Le troisième est le bloc d'incrémentation qu'on va utiliser pour incrémenter une variable à chaque itération de la boucle. De ce fait, la boucleforest très pratique pour compter ainsi que pour répéter la boucle un nombre défini de fois.

Dans l'exemple suivant, on va afficher cinq fois une boîte de dialogue à l'aide dealert(), qui affichera le numéro de chaque itération :

for (var iter = 0; iter < 5; iter++) {
alert('Itération n°' + iter);
}

Dans le premier bloc, l'initialisation, on initialise une variable appeléeiterqui vaut 0 ; le mot-clévarest requis, comme pour toute initialisation. On définit dans la condition que la boucle continue tant qu'iterest strictement inférieure à 5. Enfin, dans le bloc d'incrémentation, on indique qu'itersera incrémentée à chaque itération terminée.

Mais il ne m'affiche que « Itération n°4 » à la fin, il n'y a pas d'itération n°5 ?

C'est tout à fait normal, pour deux raisons : le premier tour de boucle porte l'indice 0, donc si on compte de 0 à 4, il y a bien 5 tours : 0, 1, 2, 3 et 4. Ensuite, l'incrémentation n'a pas lieu avant chaque itération, mais à la fin de chaque itération. Donc, le tout premier tour de boucle est fait aveciterqui vaut 0, avant d'être incrémenté.

Reprenons notre exemple

Avec les quelques points de théorie que nous venons de voir, nous pouvons réécrire notre exemple des prénoms, tout en montrant qu'une boucleforpeut être utilisée sans incrémentation :

for (var nicks = '', nick; true;) {
nick = prompt('Entrez un prénom :');
if (nick) {
nicks += nick + ' ';
} else {
break;
}
}
alert(nicks);

Essayer le code

Dans le bloc d'initialisation (le premier), on commence par initialiser nos deux variables. Vient alors le bloc avec la condition (le deuxième), qui vaut simplementtrue. On termine par le bloc d'incrémentation et… il n'y en a pas besoin ici, puisqu'il n'y a pas besoin d'incrémenter. On le fera pour un autre exemple juste après. Ce troisième bloc est vide, mais est requis. C'est pour cela que l'on doit quand même mettre le point-virgule après le deuxième bloc (la condition).

Maintenant, modifions la boucle de manière à compter combien de prénoms ont été enregistrés. Pour ce faire, nous allons créer une variable de boucle, nomméei, qui sera incrémentée à chaque passage de boucle.

for (var i = 0, nicks = '', nick; true; i++) {
nick = prompt('Entrez un prénom :');
if (nick) {
nicks += nick + ' ';
} else {
break;
}
}
alert('Il y a ' + i + ' prénoms :\n\n' + nicks);

Essayer le code

La variable de boucle a été ajoutée dans le bloc d'initialisation. Le bloc d'incrémentation a lui aussi été modifié : on indique qu'il faut incrémenter la variable de bouclei. Ainsi, à chaque passage dans la boucle,iest incrémentée, ce qui va nous permettre de compter assez facilement le nombre de prénoms ajoutés.

Portée des variables de boucle

En JavaScript, il est déconseillé de déclarer des variables au sein d'une boucle (entre les accolades), pour une raison logique : il n'y a en effet pas besoin de déclarer une même variable à chaque passage dans la boucle ! Il est conseillé de déclarer les variables directement dans le bloc d'initialisation, comme montré dans les exemples de ce cours. Mais attention : une fois que la boucle est exécutée, la variable existe toujours, ce qui explique que dans l'exemple précédent on puisse récupérer la valeur deiune fois la boucle terminée. Ce comportement est différent de celui de nombreux autres langages, dans lesquels une variable déclarée dans une boucle est « détruite » une fois la boucle exécutée.

Priorité d'exécution

Les trois blocs qui constituent la boucleforne sont pas exécutés en même temps :

  • Initialisation : juste avant que la boucle ne démarre. C'est comme si les instructions d'initialisation avaient été écrites juste avant la boucle, un peu comme pour une bouclewhile;

  • Condition : avant chaque passage de boucle, exactement comme la condition d'une bouclewhile;

  • Incrémentation : après chaque passage de boucle. Cela veut dire que, si vous faites unbreakdans une bouclefor, le passage dans la boucle lors dubreakne sera pas comptabilisé.

La boucleforest très utilisée en JavaScript, bien plus que la bouclewhile. Comme nous le verrons par la suite, le fonctionnement même du JavaScript fait que la boucleforest nécessaire dans la majorité des cas comme la manipulation des tableaux ainsi que des objets. Ce sera vu plus tard. Nous verrons aussi une variante de la bouclefor, appeléefor in, mais que nous ne pouvons aborder maintenant car elle ne s'utilise que dans certains cas spécifiques.

En résumé
  • L'incrémentation est importante au sein des boucles. Incrémenter ou décrémenter signifie ajouter ou soustraire une unité à une variable. Le comportement d'un opérateur d'incrémentation est différent s'il se place avant ou après la variable.

  • La bouclewhilepermet de répéter une liste d'instructions tant que la condition est vérifiée.

  • La boucledo whileest une variante dewhilequi sera exécutée au moins une fois, peu importe la condition.

  • La boucleforest une boucle utilisée pour répéter une liste d'instructions un certain nombre de fois. C'est donc une variante très ciblée de la bouclewhile.

  1. Q.C.M.

  2. Questionnaire didactique

  3. Écrire une boucle while

  4. Ecrire une boucle while qui exécute un prompt()