Alain Barraud Mémento informatique  
 
Accueil Logithèque - SE Photo - vidéo Internet - protocoles Site Web PC - Réseau Archives
Page ouverte le 16/05/2009

JavaScript - Partie 5 : les boucles

Dans le chapitre précédent, on a découvert les conditions et leur utilisation à travers des tests "Si… alors… sinon…".
On va voir une autre utilisation : les boucles.


Retour accueil JS


Sommaire partie 5

Des boucles ? Pour quoi faire ?

Petit exercice

En guise de présentation, on va réaliser un petit exercice pour faire connaissance avec les boucles :
afficher la liste de tous les nombres plus petits que 10 (une boite de dialogue par nombre).

Code : JavaScript
1     alert(1);
2     alert(2);
3     alert(3);
4     alert(4);
5     alert(5);
6     alert(6);
7     alert(7);
8     alert(8);
9     alert(9);
Mais c'est un peu long et très ennuyant.
Voici une autre méthode, beaucoup plus puissante, pour arriver au même résultat.

Utiliser une boucle

Ce qu'il faudrait, c'est pouvoir demander à l'ordinateur de "compter", et tant qu'il n'a pas atteint 10, d'afficher la valeur.
C'est sur ce modèle que sont conçues ce qu'on appelle les boucles : on répète une action tant que une condition est satisfaite.

Pourquoi les boucles ? Parcequ'il en existe plusieurs différentes, qui s'utilisent dans des situations elles aussi différentes.


Boucle "while"

Syntaxe et fonctionnement

Commençons par la boucle la plus simple…

En voici la syntaxe :

Code : JavaScript
1     while(condition)
2     {
3         instructions
4     }

Tant que la condition est satisfaite, on répète les instructions.
alt Si la condition n'est pas vérifiée au premier tour de boucle,
alors les instructions ne seront pas exécutées.
Voici le fonctionnement exact de la boucle, illustré par le schéma ci-contre :
# Si la condition est vérifiée,
--> Alors on exécute les instructions, et on retourne à #,
--> Sinon on passe à la suite.
Fonctionnement de la boucle "while"
boucle while

Reprenons notre exercice…

On va créer une variable qui servira à "compter".
Tant que cette variable sera inférieure à 10, on affichera un message, puis on l'incrémentera.

alt Incrémenter une variable signifie augmenter sa valeur (en général, de 1).
Décrémenter signifie diminuer sa valeur.
Ce dui donne :
Code : JavaScript
1     var i = 1; // on initialise le compteur
2     while(i < 10)/ tant que i<10 …
3     {
4         // … on affiche un message
5         alert(i);
6         i++;
7     }
alt Si on oublie d'incrémenter sa variable, la condition sera toujours vraie !
La boucle ne s'arrêtera donc jamais…
On obtiendra sûrement un message d'erreur de son navigateur nous proposant d'interrompre le script.


Boucle "for"

Présentation de cette boucle

Un code qui revient souvent…

Les boucles while sont, comme on vient de le voir, très "basiques" : la syntaxe est on ne peut plus simple !

Lors de leur utilisation, il est très fréquent d'utiliser un compteur, comme on l'a fait dans l'exemple précédent.
Ce compteur, qui n'est rien d'autre qu'une variable (souvent appelée i, mais ce n'est pas une obligation), est ensuite incrémenté (ou décrémenté) à chaque tour de boucle.

On se retrouve souvent avec un code qui ressemble à ceci :

Code : JavaScript
1     var i;
2     i = 0; // initialisation
3     while(i < 10)// condition
4     {
5         alert(i);// action
6         i++;// incrementation
7     }
Mais ce serait plus pratique avec une boucle qui regroupe tout ça !
C'est le but de cette nouvelle boucle que nous allons voir.

Une boucle qui va nous simplifier la vie

Voici la boucle for, qui regroupe tout ce que nous voulions !
Sa syntaxe :

Code : JavaScript
1     for(initialisation ; condition ; incrementation)
2     {
3         instructions
4     }
alt Ce sont bien des points-virgules qui se trouvent entre les parenthèses après le for.
Attention à ne pas les confondre avec des virgules, qui sont utilisées pour séparer les arguments des fonctions.

Ce qui donne pour le code de notre exemple :
Code : JavaScript
1     var i; // on déclare notre variable
2     for(i=0; i<10; i++) // 3-en-1 :) initialisation + condition + incrémentation
3         alert(i); // action
alt Il n'y a qu'une instruction à effectuer à chaque tour de boucle.
Les accolades sont donc devenues inutiles, c'est pourquoi elles n'ont pas été mises.

Et encore plus pratique : on peut déclarer la variable i directement dans le for, comme ceci :
Code : JavaScript
1     for(var i=0; i<10; i++)
2         alert(i);
Voilà qui est formidable !

Un peu de pratique

alt Les boucles for sont plus pratiques que les boucles while, mais uniquement dans certains cas !
Il est parfois plus judicieux d'utiliser une boucle while, notamment lorsqu'on ne retrouve pas cette structure "initialisation / condition / incrémentation" (nous en verrons des exemples par la suite).
Petit exemple

faire une boucle (en utilisant for) qui fait la somme des nombres de 1 à 10 (inclus).

Code : JavaScript
1     var i;
2             var somme = 0; // variable pour le resultat
3             for(i=0; i<10; i++)
4                     somme += i; // on ajoute la valeur du compteur à notre resultat
5             alert(somme);

Ce qu'il ne faut pas faire

Avec les boucles for, on peut mettre tout plein de trucs dans les parenthèses.
Et avec une indentation "excentrique", ainsi qu'avec des noms de variables qui ne veulent rien dire, on obtient des résultats vraiment géniaux, comme ici :

Code : JavaScript
1     var azerty=0,arezty;
2     for(arezty=0;azertyi<10;arezty+= azerty=1 +azerty);alert(arezty);
Que fait ce code ? Eh bien comme l'exemple juste avant, il fait la somme des nombres de 1 à 10…
alt Ce code est un excellent exemple… de ce qu'il ne faut pas faire !
A moins d' aimer les codes illisibles…

Quelques conseils concernant les boucles for :
  • éviter de modifier la variable qui sert de compteur à l'extérieur des parenthèses du for, qui sont prévues pour ça.
  • Inversement, éviter de mettre entre ces parenthèses du code qui ne concerne pas directement cette variable.
  • Pour rappel, donner des noms explicites et pas trop longs aux variables (i ou j, parfois cpt, étant des noms classiques pour des compteurs).
  • Penser également à bien indenter son code, et à mettre quelques commentaires, (uniquement) s'ils s'avèrent nécessaires.


Boucle "do … while"

Le dernier type de boucle ressemble assez fortement à while.

La syntaxe

Sa syntaxe est la suivante :

Code : JavaScript
1     do
2     {
3             instructions
4     }
5     while(condition);
alt Ici, le while est placé à la fin de la boucle, après les instructions qui le concernent : c'est pour ça qu'il est suivit d'un point-virgule.

Comment ça marche ?
On a pu remarquer que le while est placé à la fin de la boucle : c'est ce qui fait la différence avec la boucle "while" vue plus haut.
Quelle différence ?
Le test est effectué après les instructions, ce qui veut dire que ces dernières seront exécutées au moins une fois, quelle que soit la condition (cf. le petit schéma ci-contre).
Fonctionnement de la boucle "do…while"
boucle do…while
Petit exemple…

Une des utilisations possibles : on demande des noms à l'utilisateur (avec prompt()) tant qu'il ne clique pas sur "Annuler" (ou qu'il ne laisse pas le champ vide).
Pour l'instant, on ne s'occupe pas d'enregistrer tous les noms qui seront tapés.

alt Rappel : la syntaxe est la suivante :
Code : JavaScript
1     var nom = prompt('Entrez un nom);
Si l'utilisateur clique sur "Annuler", la variable vaudra null.
Voici une manière de coder cet exemple :
Code : JavaScript
1     var saisie;
2     do
3             saisie = prompt("Entrez un nom, ou cliquez sur Annuler pour quitter");
4     while(saisie != null && saisie != ' ' );

ou bien, en "simplifiant" un peu :
Code : JavaScript
1     var saisie;
2     do
3             saisie = prompt("Entrez un nom, ou cliquez sur Annuler pour quitter");
4     while(saisie); // ca revient au meme que dans l'exemple ci-dessus


Instructions de contrôle

Après avoir vu les types de boucles, nous allons aborder un dernier point dans ce chapitre : les instructions de contrôle, qui ne sont rien d'autre que des instructions qui agissent sur les boucles.

break

Comment ça marche ?

La première, qui se prénomme break ("casser" en anglais), est très simple d'utilisation. Elle arrête immédiatement la boucle dans laquelle elle se trouve (le script continue normalement, en reprenant juste après la boucle en question).

Exemple :

Code : JavaScript
1     var i;
2     for(i=0; i<20; i++)
3     {
4         if(3*i > 10)
5             break;
6         alert(3*i);
3     }
On va afficher les multiples de 3. Mais si un multiple dépasse 10, on s'arrête.

Un code moins bien "organisé"
alt Cette instruction est très pratique dans certains cas.
Cependant, elle est à éviter autant que possible : il vaut mieux créer une condition plus complète pour votre boucle, plutôt que d'insérer des if avec des break dans toute la boucle.

L'exemple plus haut est correct du point de vue de la syntaxe, mais c'est exactement l'utilisation qu'il ne faut pas faire de break.
Voici une manière bien mieux structurée pour ce même exemple :

Code : JavaScript
1     var i;
2     for(i=0; 3*i<=10; i++)
3         alert(3*i);
Ici, tout ce qui concerne la boucle se trouve entre les parenthèses du for, ce qui rend le code bien mieux "organisé".

Cas de boucles imbriquées

Et si on met un break à l'intérieur d'une boucle, qui est elle-même à l'intérieur d'une autre boucle ?

Dans ce cas, il s'applique uniquement à la boucle la plus "imbriquée".

Dans l'exemple qui suit, le break s'applique seulement à la boucle avec la variable j.

Code : JavaScript
1     var i, j;
2     for(i=0; i<5; i++)
3     {
4         for(j=0; j<5; i++)
5         {
6             if(j == 2)
7                 break;
8         }
9     }

continue

L'instruction de contrôle suivante, continue, s'utilise de manière quelque peu semblable.

Fonctionnement…

Lorsque l'instruction continue est rencontrée, toutes les instructions qui suivront seront ignorées, jusqu'à ce qu'on arrive à la fin des instructions de la boucle. La boucle continue ensuite normalement.
Pour simplifier, continue permet en quelque sorte de "sauter" certains tours de la boucle.

… et exemple
Code : JavaScript
1     var i;
2     for(i=-5; i<=5; i++)
3     {
4         if(i == 0)
5             continue;
7         alert(";
8         }
9     }

Lorsque i vaut 0, on saute les instructions qui restent dans la boucle (ici, alert()), puis on reprend avec i = 1 (la valeur suivante).

On affiche donc le message pour i = -5, -4, -3, -2, -1, (on saute le 0), 1, 2, 3, 4 et 5.


Application

Mise en pratique de ce qu'on vient de voir.

Exercice

Le script a créer est celui du SdZ… C'est un script qui est utilisé sur ce site.

Le sujet

Exercice tiré du zCode…
On va s'intéresser ici au bouton servant à insérer une liste à puces.
Le script a pour rôle de demander le contenu de chaque puce à l'utilisateur, et de créer le zCode correspondant.

alt Rappel : zCode d'une liste à puces
Code : Zcode
1     <liste>
2     <puce>Contenu de la puce 1</puce>
3     <puce>Contenu de la puce 2</puce>
4     …
5     </liste>

Quelques consignes pour guider

On va demander le contenu de chaque puce grâce à prompt().
C'est ici qu'on va devoir utiliser une boucle : on demande tant que l'utilisateur ne laisse pas le champ vide.

Au final, on va récupérer le zCode dans une variable.
On l'affichera grâce à alert() pour vérifier le fonctionnement du script.

Correction

Correction en plusieurs &eactute;tapes

Version 1 : "bof bof"
Code : JavaScript
1     // initialisations
2     var zCode = '<liste>\n';
3     var saisie = '';
4
5     // boucle
6     do 7     {
8         saisie = prompt("Contenu de la puce ?":);
9         if(saisie)
10             zCode += "<puce>" + saisie + "</puce>\n";
11     }while(saisie);
12
13     // fin
14     zCode += "</liste>";
15     alert(zCode);

Plusieurs points ne sont pas très "propres".

Tout d'abord, si on ne remplit aucune puce, on se retrouve avec ceci :

Code : JavaScript
1     <liste>
2     </liste>
Certes, un "détail", mais si facile à corriger que c'est dommage de le laisser comme ça.

Autre remarque : à quelques lignes près, on voit deux fois le même test : if(saisie) et while(saisie).
Ce n'est jamais bien bon de se répéter (par exemple, si on doit modifier la condition, c'est un peu relou de le faire deux fois).

Si on veut modifier ça, il va falloir enregistrer la saisie dans une variable, pour l'ajouter au zCode uniquement au tour de boucle suivant (une fois que le test de la boucle aura été fait)… Ce qui complique un peu l'affaire.

Version 1 : améliorée

Voici le même code, après avoir modifié les problèmes soulignés ci-dessus.

Code : JavaScript
1     var zcCode = '';
2     var saisie = '';
3     // variable "temporaire", pour le 2e point
4     var texte = '<liste>\n';
5
6     do
7     {
8     // on ajoute le texte saisi au tour precedent
9         zCode += texte;
10     // on demande du texte et on enregistre dans la variable "temporaire"
11         saisie = prompt("Contenu de la puce ?":);
12         texte = "<puce>" + saisie + "</puce>\n";
13     }while(saisie);
14
15     // le 1er "detail"
16     if(zCode == '<liste>\n')
17         zCode = '';
18     else
19         zCode = "</liste>";
20
21     alert(zCode);

Version 2 : tout-en-un

Une autre solution consisterait à enregistrer et à tester en même temps le texte saisi.
Comment ? Eh bien en plaçant l'affectation dans la condition.
En voici le principe :

Code : JavaScript
1     var saisie;
2     while (saisie = prompt("Texte"))
3     // instructions

ce qui équivaut, pour rappel, à ceci :
Code : JavaScript
1     var saisie;
2     while (saisie = prompt("Texte")) == true )
3     // instructions
alt Ne pas confondre le = (opérateur d'affectation) avec == (opérateur de comparaison) !

Il faut bien comprendre que cette condition (appelée à chaque tour de boucle) se compose de deux étapes :
  • tout d'abord, l'instruction saisie = prompt("Texte"), que l'on comprend maintenant sans difficulté.
  • Ensuite, le test, avec la nouvelle valeur de la variable modifiée ci-dessus.
Pour revenir à notre exemple, ça nous donne ceci :
Code : JavaScript
1     // initialisations
2     var zCode = '<liste>\n';
3     var saisie;
4
5     // boucle
6     while(saisie = prompt("Contenu de la puce ?"))
7         zCode += "<puce>" + saisie + "</puce>\n";
8
9     // finitions
10     if(zCode == '<liste>\n')
11         zCode = '';
12     else
13         zCode = "</liste>";
14
15     alert(zCode);