034.3 Leçon 1
Certification : |
Web Development Essentials |
---|---|
Version : |
1.0 |
Thème : |
034 Programmation JavaScript |
Objectif : |
034.3 Structures de contrôle et fonctions JavaScript |
Leçon : |
1 sur 2 |
Introduction
Comme tout autre langage de programmation, le code JavaScript est une collection d’instructions qui indique à un interpréteur d’instructions ce qu’il faut faire dans un ordre séquentiel. Cependant, cela ne signifie pas que chaque instruction ne doit être exécutée qu’une seule fois ou qu’elle ne doit pas être exécutée du tout. La plupart des instructions ne doivent être exécutées que lorsque des conditions spécifiques sont remplies. Même lorsqu’un script est déclenché de manière asynchrone par des événements indépendants, il doit souvent vérifier un certain nombre de variables de contrôle pour trouver la bonne portion de code à exécuter.
Instructions If
La structure de contrôle la plus simple est donnée par l’instruction if
, qui exécutera l’instruction immédiatement après si la condition spécifiée est vraie. JavaScript considère que les conditions sont vraies si la valeur évaluée est différente de zéro. Tout ce qui se trouve à l’intérieur des parenthèses après le mot if
(les espaces sont ignorés) sera interprété comme une condition. Dans l’exemple suivant, le nombre littéral 1
est la condition :
if ( 1 ) console.log("1 is always true");
Le nombre 1
est explicitement écrit dans cet exemple de condition, il est donc traité comme une valeur constante (il reste le même tout au long de l’exécution du script) et il donnera toujours vrai lorsqu’il est utilisé comme expression conditionnelle. Le mot true
(sans les guillemets) pourrait également être utilisé à la place de 1
, car il est également traité comme une valeur littérale vraie par le langage. L’instruction console.log
imprime ses arguments dans la fenêtre console du navigateur.
Tip
|
La console du navigateur affiche les erreurs, les avertissements et les messages d’information envoyés avec l’instruction JavaScript |
Bien que syntaxiquement correcte, l’utilisation d’expressions constantes dans les conditions n’est pas très utile. Dans une application réelle, vous voudrez probablement tester la véracité d’une variable :
let my_number = 3;
if ( my_number ) console.log("The value of my_number is", my_number, "and it yields true");
La valeur assignée à la variable my_number
(3
) est non nulle, donc elle donne vrai. Mais cet exemple n’est pas d’usage courant, car vous avez rarement besoin de tester si un nombre est égal à zéro. Il est beaucoup plus courant de comparer une valeur à une autre et de tester si le résultat est vrai :
let my_number = 3;
if ( my_number == 3 ) console.log("The value of my_number is", my_number, "indeed");
L’opérateur de comparaison double égal est utilisé car l’opérateur simple égal est déjà défini comme l’opérateur d’affectation. La valeur de chaque côté de l’opérateur est appelée un opérande. L’ordre des opérandes n’a pas d’importance et toute expression qui renvoie une valeur peut être un opérande. Voici une liste d’autres opérateurs de comparaison disponibles :
value1 == value2
-
Vrai si
value1
est égale àvalue2
. value1 != value2
-
Vrai si
value1
n’est pas égale àvalue2
. value1 < value2
-
Vrai si
value1
est inférieur àvalue2
. value1 > value2
-
Vrai si
value1
est plus grand quevalue2
. value1 <= value2
-
Vrai si
value1
est inférieur ou égal àvalue2
. value1 >= value2
-
Vrai si
value1
est supérieur ou égal àvalue2
.
En général, il importe peu que l’opérande à gauche de l’opérateur soit une chaîne de caractères et que l’opérande à droite soit un nombre, tant que JavaScript est capable de convertir l’expression en une comparaison significative. Ainsi, la chaîne contenant le caractère 1
sera traitée comme le nombre 1 lorsqu’elle sera comparée à une variable numérique. Pour s’assurer que l’expression ne donne un résultat vrai que si les deux opérandes sont exactement du même type et de la même valeur, l’opérateur d’identité stricte ===
doit être utilisé à la place de ==
. De même, l’opérateur de non-identité stricte !==
est évalué comme vrai si le premier opérande n’est pas exactement du même type et de la même valeur que le second opérateur.
Optionnellement, la structure de contrôle if
peut exécuter une autre instruction lorsque l’expression est évaluée comme fausse :
let my_number = 4;
if ( my_number == 3 ) console.log("The value of my_number is 3");
else console.log("The value of my_number is not 3");
L’instruction else
doit suivre immédiatement l’instruction if
. Jusqu’à présent, nous n’avons exécuté qu’une seule instruction lorsque la condition est vérifiée. Pour exécuter plus d’une instruction, vous devez les entourer d’accolades :
let my_number = 4;
if ( my_number == 3 )
{
console.log("The value of my_number is 3");
console.log("and this is the second statement in the block");
}
else
{
console.log("The value of my_number is not 3");
console.log("and this is the second statement in the block");
}
Un groupe d’une ou de plusieurs instructions délimitées par une paire d’accolades est appelé bloc. Il est courant d’utiliser des instructions de type bloc même lorsqu’il n’y a qu’une seule instruction à exécuter, afin de rendre le style de codage cohérent dans tout le script. En outre, JavaScript n’exige pas que les accolades ou les instructions soient sur des lignes séparées, mais cela améliore la lisibilité et facilite la maintenance du code.
Les structures de contrôle peuvent être imbriquées les unes dans les autres, mais il est important de ne pas confondre les accolades ouvrantes et fermantes de chaque bloc d’instructions :
let my_number = 4;
if ( my_number > 0 )
{
console.log("The value of my_number is positive");
if ( my_number % 2 == 0 )
{
console.log("and it is an even number");
}
else
{
console.log("and it is an odd number");
}
} // end of if ( my_number > 0 )
else
{
console.log("The value of my_number is less than or equal to 0");
console.log("and I decided to ignore it");
}
Les expressions évaluées par l’instruction if
peuvent être plus élaborées que de simples comparaisons. C’est le cas dans l’exemple précédent, où l’expression arithmétique my_number % 2
était employée à l’intérieur des parenthèses dans le if
imbriqué. L’opérateur %
renvoie le reste après avoir divisé le nombre à sa gauche par le nombre à sa droite. Les opérateurs arithmétiques comme %
sont prioritaires sur les opérateurs de comparaison comme ==
, la comparaison utilisera donc le résultat de l’expression arithmétique comme opérande gauche.
Dans de nombreuses situations, les structures conditionnelles imbriquées peuvent être combinées en une seule structure en utilisant des opérateurs logiques. Si nous ne nous intéressons qu’aux nombres pairs positifs, par exemple, une seule structure if
pourrait être utilisée :
let my_number = 4;
if ( my_number > 0 && my_number % 2 == 0 )
{
console.log("The value of my_number is positive");
console.log("and it is an even number");
}
else
{
console.log("The value of my_number either 0, negative");
console.log("or it is a negative number");
}
L’opérateur double esperluette &&
dans l’expression évaluée est l’opérateur logique AND. Il n’est évalué comme vrai que si l’expression à sa gauche et l’expression à sa droite sont évaluées comme vraies. Si vous voulez faire correspondre des nombres qui sont soit positifs, soit pairs, il faut utiliser l’opérateur ||
à la place, qui représente l’opérateur logique OR :
let my_number = -4;
if ( my_number > 0 || my_number % 2 == 0 )
{
console.log("The value of my_number is positive");
console.log("or it is a even negative number");
}
Dans cet exemple, seuls les nombres impairs négatifs ne correspondront pas aux critères imposés par l’expression composite. Si vous avez l’intention contraire, c’est-à-dire de ne faire correspondre que les nombres impairs négatifs, ajoutez l’opérateur logique NOT !
au début de l’expression :
let my_number = -5;
if ( ! ( my_number > 0 || my_number % 2 == 0 ) )
{
console.log("The value of my_number is an odd negative number");
}
L’ajout des parenthèses dans l’expression composite force l’expression qu’elles encadrent à être évaluée en premier. Sans ces parenthèses, l’opérateur NOT ne s’appliquerait qu’à my_number > 0
et ensuite l’expression OR serait évaluée. Les opérateurs &&
et ||
sont appelés opérateurs logiques binaires, car ils nécessitent deux opérandes. L’opérateur !
est appelé opérateur logique unaire, car il ne nécessite qu’un seul opérande.
Structures switch
Bien que la structure if
soit assez polyvalente et suffisante pour contrôler le flux du programme, la structure de contrôle switch
peut être plus appropriée lorsque des résultats autres que vrai ou faux doivent être évalués. Par exemple, si nous voulons prendre une action distincte pour chaque élément choisi dans une liste, il sera nécessaire d’écrire une structure if
pour chaque évaluation :
// Available languages: en (English), es (Spanish), pt (Portuguese)
let language = "pt";
// Variable to register whether the language was found in the list
let found = 0;
if ( language == "en" )
{
found = 1;
console.log("English");
}
if ( found == 0 && language == "es" )
{
found = 1;
console.log("Spanish");
}
if ( found == 0 && language == "pt" )
{
found = 1;
console.log("Portuguese");
}
if ( found == 0 )
{
console.log(language, " is unknown to me");
}
Dans cet exemple, une variable auxiliaire found
est utilisée par toutes les structures if
pour savoir si une correspondance s’est produite. Dans un cas comme celui-ci, la structure switch
effectuera la même tâche, mais de manière plus succincte :
switch ( language )
{
case "en":
console.log("English");
break;
case "es":
console.log("Spanish");
break;
case "pt":
console.log("Portuguese");
break;
default:
console.log(language, " not found");
}
Chaque case
imbriqué est appelé une clause. Lorsqu’une clause correspond à l’expression évaluée, elle exécute les instructions qui suivent les deux points jusqu’à l’instruction break
. La dernière clause n’a pas besoin d’instruction break
et elle est souvent utilisée pour définir l’action par défaut lorsqu’aucune autre correspondance ne se produit. Comme on le voit dans l’exemple, la variable auxiliaire n’est pas nécessaire dans la structure switch
.
Warning
|
|
Si plusieurs clauses déclenchent la même action, vous pouvez combiner deux ou plusieurs conditions case
:
switch ( language )
{
case "en":
case "en_US":
case "en_GB":
console.log("English");
break;
case "es":
console.log("Spanish");
break;
case "pt":
case "pt_BR":
console.log("Portuguese");
break;
default:
console.log(language, " not found");
}
Boucles
Dans les exemples précédents, les structures if
et switch
étaient bien adaptées aux tâches qui doivent s’exécuter une seule fois après avoir passé un ou plusieurs tests conditionnels. Cependant, il y a des situations où une tâche doit s’exécuter de façon répétée — dans ce qu’on appelle une boucle — tant que son expression conditionnelle continue à être testée comme vraie. Si vous avez besoin de savoir si un nombre est premier, par exemple, vous devrez vérifier si la division de ce nombre par tout entier supérieur à 1 et inférieur à lui-même a un reste égal à 0. Si c’est le cas, le nombre a un facteur entier et il n’est pas premier. (Il ne s’agit pas d’une méthode rigoureuse ou efficace pour trouver des nombres premiers, mais elle fonctionne comme un exemple simple). Les structures de contrôle en boucle sont plus adaptées à de tels cas, en particulier l’instruction while
:
// A naive prime number tester
// The number we want to evaluate
let candidate = 231;
// Auxiliary variable
let is_prime = true;
// The first factor to try
let factor = 2;
// Execute the block statement if factor is
// less than candidate and keep doing it
// while factor is less than candidate
while ( factor < candidate )
{
if ( candidate % factor == 0 )
{
// The remainder is zero, so the candidate is not prime
is_prime = false;
break;
}
// The next factor to try. Simply
// increment the current factor by one
factor++;
}
// Display the result in the console window.
// If candidate has no integer factor, then
// the auxiliary variable is_prime still true
if ( is_prime )
{
console.log(candidate, "is prime");
}
else
{
console.log(candidate, "is not prime");
}
Le bloc d’instructions qui suit l’instruction while
s’exécutera de manière répétée tant que la condition factor < candidate
est vraie. Elle s’exécutera au moins une fois, tant que nous initialiserons la variable factor
avec une valeur inférieure à candidate
. La structure if
imbriquée dans la structure while
va évaluer si le reste de candidate
divisé par factor
est égal à zéro. Si c’est le cas, le nombre candidat n’est pas premier et la boucle peut se terminer. L’instruction break
terminera la boucle et l’exécution sautera à la première instruction après le bloc while
.
Notez que le résultat de la condition utilisée par l’instruction while
doit changer à chaque boucle, sinon l’instruction de bloc bouclera “à l’infini”. Dans l’exemple, nous incrémentons la variable factor
‒ le prochain diviseur que nous voulons essayer ‒ et cela garantit que la boucle se terminera à un moment donné.
Cette simple implémentation d’un testeur de nombres premiers fonctionne comme prévu. Cependant, nous savons qu’un nombre qui n’est pas divisible par deux ne sera pas divisible par un autre nombre pair. Par conséquent, nous pourrions simplement sauter les nombres pairs en ajoutant une autre instruction if
:
while ( factor < candidate )
{
// Skip even factors bigger than two
if ( factor > 2 && factor % 2 == 0 )
{
factor++;
continue;
}
if ( candidate % factor == 0 )
{
// The remainder is zero, so the candidate is not prime
is_prime = false;
break;
}
// The next number that will divide the candidate
factor++;
}
L’instruction continue
est similaire à l’instruction break
, mais au lieu de terminer cette itération de la boucle, elle va ignorer le reste du bloc de la boucle et commencer une nouvelle itération. Notez que la variable factor
a été modifiée avant l’instruction continue
, sinon la boucle aurait le même résultat à l’itération suivante. Cet exemple est trop simple et sauter une partie de la boucle n’améliorera pas vraiment ses performances, mais sauter les instructions redondantes est très important pour écrire des applications efficaces.
Les boucles sont si couramment utilisées qu’elles existent dans de nombreuses variantes différentes. La boucle for
est particulièrement adaptée à l’itération de valeurs séquentielles, car elle nous permet de définir les règles de la boucle en une seule ligne :
for ( let factor = 2; factor < candidate; factor++ )
{
// Skip even factors bigger than two
if ( factor > 2 && factor % 2 == 0 )
{
continue;
}
if ( candidate % factor == 0 )
{
// The remainder is zero, so the candidate is not prime
is_prime = false;
break;
}
}
Cet exemple produit exactement le même résultat que l’exemple précédent avec while
, mais son expression entre parenthèses comprend trois parties, séparées par des points-virgules : l’initialisation (let factor = 2
), la condition de la boucle (factor < candidate
), et l’expression finale à évaluer à la fin de chaque itération de la boucle (factor+`). Les instructions `continue` et `break` s'appliquent également aux boucles `for`. L'expression finale entre parenthèses (`factor+
) sera évaluée après l’instruction continue
, elle ne doit donc pas se trouver à l’intérieur du bloc d’instructions, sinon elle sera incrémentée deux fois avant la prochaine itération.
JavaScript dispose de types spéciaux de boucles for
pour travailler avec des objets de type tableau. Nous pourrions, par exemple, vérifier un tableau de variables candidates au lieu d’une seule :
// A naive prime number tester
// The array of numbers we want to evaluate
let candidates = [111, 139, 293, 327];
// Evaluates every candidate in the array
for (candidate of candidates)
{
// Auxiliary variable
let is_prime = true;
for ( let factor = 2; factor < candidate; factor++ )
{
// Skip even factors bigger than two
if ( factor > 2 && factor % 2 == 0 )
{
continue;
}
if ( candidate % factor == 0 )
{
// The remainder is zero, so the candidate is not prime
is_prime = false;
break;
}
}
// Display the result in the console window
if ( is_prime )
{
console.log(candidate, "is prime");
}
else
{
console.log(candidate, "is not prime");
}
}
L’instruction for (candidat des candidats)
attribue un élément du tableau candidates
à la variable candidate
et l’utilise dans le bloc d’instructions, en répétant le processus pour chaque élément du tableau. Vous n’avez pas besoin de déclarer la variable candidate
séparément, car la boucle for
la définit. Enfin, le même code que celui de l’exemple précédent est imbriqué dans cette nouveau bloc d’instructions, mais cette fois-ci en testant chaque candidat du tableau.
Exercices guidés
-
Quelles valeurs de la variable
my_var
correspondent à la conditionmy_var > 0 && my_var < 9
? -
Quelles valeurs de la variable
my_var
correspondent à la conditionmy_var > 0 || my_var < 9
? -
Combien de fois la boucle
while
suivante exécutera-t-elle son bloc d’instructions ?let i = 0; while ( 1 ) { if ( i == 10 ) { continue; } i++; }
Exercices d’exploration
-
Que se passe-t-il si l’opérateur d’affectation égale
=
est utilisé au lieu de l’opérateur de comparaison double égale==
? -
Écrivez un fragment de code utilisant la structure de contrôle
if
où une comparaison d’égalité ordinaire retournera vrai, mais pas une comparaison d’égalité stricte. -
Réécrivez l’instruction
for
suivante en utilisant l’opérateur logique unaire NOT dans la condition de la boucle. Le résultat de la condition doit être le même.for ( let factor = 2; factor < candidate; factor++ )
-
En vous basant sur les exemples de cette leçon, écrivez une structure de contrôle en boucle qui affiche tous les facteurs entiers d’un nombre donné.
Résumé
Cette leçon explique comment utiliser les structures de contrôle dans le code JavaScript. Les structures conditionnelles et les boucles sont des éléments essentiels de tout paradigme de programmation, et le développement web avec JavaScript ne fait pas exception. La leçon aborde les concepts et procédures suivants :
-
L’instruction
if
et les opérateurs de comparaison. -
Comment utiliser la structure
switch
aveccase
,default
, etbreak
. -
La différence entre une comparaison ordinaire et une comparaison stricte.
-
Les structures de contrôle des boucles :
while
etfor
.
Réponses aux exercices guidés
-
Quelles valeurs de la variable
my_var
correspondent à la conditionmy_var > 0 && my_var < 9
?Seuls les nombres qui sont à la fois supérieurs à 0 et inférieurs à 9. L’opérateur logique
&&
(AND) exige que les deux comparaisons soient respectées. -
Quelles valeurs de la variable
my_var
correspondent à la conditionmy_var > 0 || my_var < 9
?L’utilisation de l’opérateur logique
||
(OR) permet de faire correspondre n’importe quel nombre, car tout nombre sera soit supérieur à 0, soit inférieur à 9. -
Combien de fois la boucle
while
suivante exécutera-t-elle son bloc d’instructions ?let i = 0; while ( 1 ) { if ( i == 10 ) { continue; } i++; }
Le bloc se répétera à l’infini, car aucune condition d’arrêt n’a été fournie.
Réponses aux exercices d’exploration
-
Que se passe-t-il si l’opérateur d’affectation égale
=
est utilisé au lieu de l’opérateur de comparaison double égale==
?La valeur située à droite de l’opérateur est affectée à la variable située à gauche et le résultat est transmis à la comparaison, ce qui peut ne pas être le comportement souhaité.
-
Écrivez un fragment de code utilisant la structure de contrôle
if
où une comparaison d’égalité ordinaire retournera vrai, mais pas une comparaison d’égalité stricte.let a = "1"; let b = 1; if ( a == b ) { console.log("An ordinary comparison will match."); } if ( a === b ) { console.log("A strict comparison will not match."); }
-
Réécrivez l’instruction
for
suivante en utilisant l’opérateur logique unaire NOT dans la condition de la boucle. Le résultat de la condition doit être le même.for ( let factor = 2; factor < candidate; factor++ )
Réponse :
for ( let factor = 2; ! (factor >= candidate); factor++ )
-
En vous basant sur les exemples de cette leçon, écrivez une structure de contrôle en boucle qui affiche tous les facteurs entiers d’un nombre donné.
for ( let factor = 2; factor <= my_number; factor++ ) { if ( my_number % factor == 0 ) { console.log(factor, " is an integer factor of ", my_number); } }