Apprendre JS : Algorithmie
Variables, tableaux, conditions, boucles, fonctions... Découvrons la syntaxe de base de JavaScript pour écrire des algorithmes.
Par définition, un algorithme est caractérisé par un ensemble d’opérations ordonnées et finies devant être suivies dans l’ordre pour résoudre un problème. On assemble plusieurs algorithmes entre eux pour créer un programme informatique.
Un algorithme est une reproduction automatisée d’un raisonnement de l’homme.
Pour retranscrire nos raisonnements, on fait appel à de nombreux composants algorithmiques qui constituent la syntaxe de nos algorithmes. Étudions ensemble les concepts élémentaires et leur syntaxe en JavaScript.
Données
Il serait difficile de réaliser un algorithme sans pouvoir stocker des données. Découvrons comment déclarer des variables, constantes et tableaux en JavaScript.
Variables
Une variable est une case mémoire dans laquelle il est possible de stocker une information, une donnée. Cette case mémoire sera identifiée par un nom.
Il existe 2 mots-clés pour déclarer des variables en JavaScript : let
et var
. La valeur stockée peut être de nombreux types, dont les 3 principaux sont :
- Nombre : entier, décimal…
- Chaîne de caractères : caractère unique, chaîne courte, chaîne longue… - s’écrit entre guillemets simples
' '
ou doubles" "
. - Booléen : vrai (
true
) ou faux (false
) - …
let firstname = "toto"; // ou var firstname = "toto" ...
let weight = 58.5;
let hungry = true;
En JavaScript, on terminait historiquement nos instructions par un ;
, mais ce caractère n’est plus obligatoire aujourd’hui.
Quand on affecte une valeur à une variable on dit qu’on l’initialise. Il est également possible de déclarer une variable sans l’initialiser tout de suite.
let myVariable; // Ici sa valeur est "undefined"
Je vous invite à consulter cet article pour en savoir plus sur les différences entre let
, var
et const
en JavaScript.
Constantes
Une constante est similaire à une variable, à la seule différence que sa valeur ne pourra pas changer. Il s’agit d’une donnée en lecture seule. On déclare une constante avec le mot-clé const
.
const max_speed = 90;
Tableaux
Les tableaux sont en quelque sorte des super variables pour stocker plusieurs informations, de manière structurée.
On les déclare de la même manière que des variables classiques avec les mots-clés let
ou var
.
Concernant leurs valeurs, on les écrit entre crochets []
ou en créant un « objet tableau » avec new Array()
. On sépare les valeurs avec des virgules.
let fruits = ["Pomme", "Poire", "Banane"];
let fruits = new Array("Pomme", "Poire", "Banane"); // Equivalent
Pour accéder aux données stockées dans un tableau, on les extrait par leur indice.
Chaque valeur stockée dans un tableau est associée à un indice, commençant à 0
. Pour récupérer une valeur, on fait : nomTableau[indiceValeur]
:
let fruits = ["Pomme", "Poire", "Banane"];
console.log(fruits[0]); // Affiche "Pomme"
console.log(fruits[1]); // Affiche "Poire"
console.log(fruits[2]); // Affiche "Banane"
console.log(fruits[3]); // Erreur ! Affiche "undefined", car on sort du tableau
Il est également possible de stocker un tableau dans un tableau ! À la différence des tableaux unidimensionnels précédents, on appellera un tableau de ce type : tableau multidimensionnel ou tableau imbriqué.
Pour une meilleure lisibilité, on indentera généralement les sous-tableaux :
// Déclaration
let users = [
["Pierre", "Moulin", 34],
["Paul", "Dupont", 27],
["Jacques", "Durand", 31]
];
// Pour y accéder, on spécifiera un indice pour chaque dimension
console.log(users[1]); // Affiche ["Paul", "Dupont", 27]
console.log(users[1][2]); // Affiche 27
Objets (littéraux)
Nous ne rentrerons dans ce cours pas dans les détails de la Programmation Orientée Objet (POO), mais retenez simplement qu’en développement informatique, un objet est une structure de données riche permettant de stocker des données et des mécaniques associées.
Les objets permettent de représenter des entités du monde réel ou des concepts abstraits de manière organisée et encapsulée.
En JavaScript, un objet littéral est une façon de définir ces objets en utilisant une syntaxe concise et facile à comprendre. Il s’agit d’une collection de paires clé-valeur.
- Clé : Aussi appelée propriété, décrit quel genre de données est attendu.
- Valeur : Pouvant être de n’importe quel type de données (texte, nombre, booléen… y compris des tableaux ou d’autres objets).
La syntaxe générale pour créer un objet littéral est la suivante :
const objet = {
cle1: valeur1,
cle2: valeur2,
// ...
};
Voici un exemple concret :
const user = {
firstname: 'John',
lastname: 'Doe',
age: 30,
address: {
street: '123 rue des Pyrénées',
city: 'Bordeaux',
country: 'France'
},
hobbies: ['lecture', 'voyage', 'musique']
};
Les valeurs peuvent être de n’importe quel type de données, y compris des chaînes de caractères, des nombres, des tableaux, des objets imbriqués, des fonctions et d’autres objets littéraux.
Pour accéder aux valeurs d’un objet littéral, on utilise la notation pointée objet.cle
ou la notation entre crochets objet['cle']
.
console.log(user.lastname); // Affiche "Doe"
console.log(user['firstname']); // Affiche "John"
console.log(user.address.city); // Affiche "Bordeaux"
console.log(user['hobbies'][0]); // Affiche "lecture"
Il est également possible de redéfinir une propriété :
user.firstname = "Jane";
console.log(user.firstname); // Affiche "Jane"
Les objets littéraux en JavaScript sont très flexibles et permettent de créer des structures de données complexes pour organiser et manipuler les données de vos sites / applications.
Traitement
Stocker des données, c’est bien… les manipuler, c’est mieux. Pour cela place aux opérations, conditions, boucles et fonctions !
Opérations élémentaires
Opérations arithmétiques
En JavaScript, il est possible d’additionner, soustraire, multiplier, diviser des variables entre elles en utilisant les opérateurs arithmétiques élémentaires +
, -
, *
et /
. Il est même possible de calculer le modulo (reste de la division) de deux nombres avec l’opérateur %
.
let a = 4;
let b = 7;
// Somme de 2 variables
let addition = a + b;
// Soustraction de 2 variables
let soustraction = b - a;
// Multiplication de 2 variables
let multiplication = a * b;
// Division de 2 variables
let division = b / a;
// Modulo de 2 variables
let modulo = b % a;
// Note : pour les opérations plus complexes (racine carrée, exponentielle, factorielle...), on fera appel à des fonctions
Concaténation
Si vous souhaitez afficher des variables à côté de chaînes de caractères ou à côté d’autres variables (concaténation), on utilise l’opérateur +
.
let firstname = "Toto";
console.log("Hello " + firstname);
Il est également possible d’utiliser l’écriture par template en encadrant le texte par des backticks
(Alt Gr+7
) et en délimitant la/les variable(s) par ${variable}
.
let firstname = "Toto";
console.log(`Hello ${firstname}`);
Cette syntaxe s’avère plus concise lors de concaténations multiples, en évitant de fermer-ouvrir-fermer-ouvrir… la chaîne de caractères.
Conditions
Les conditions sont des structures algorithmiques extrêmement fréquentes et utiles qui se traduisent par « fais ceci, si cela ». Notre cerveau analyse constamment des situations conduisant à la prise de décision.
if
, else if
, else
On déclare une condition avec le mot-clé if
(littéralement « si »).
Une condition s’écrit de la forme if (condition) { ... traitement ... }
- Si la condition est vraie : renvoie
true
. - Si la condition est fausse : renvoie
false
.
Mais alors comment écrire ces conditions ? Avec des opérateurs de comparaison.
Opérateurs de comparaison
Il existe 8 grands opérateurs de comparaison.
Opérateur | Usage | Description |
---|---|---|
== | val1 == val2 | Teste une égalité (valeur) |
=== | val1 === val2 | Teste une égalité stricte (valeur + type) |
!= | val1 != val2 | Teste une différence (valeur) |
!== | val1 !== val2 | Teste une différence stricte (valeur + type) |
< | val1 < val2 | Teste si une valeur est strictement inférieure à une autre |
> | val1 > val2 | Teste si une valeur est strictement supérieure à une autre |
<= | val1 <= val2 | Teste si une valeur est inférieure ou égale à une autre |
>= | val1 >= val2 | Teste si une valeur est supérieure ou égale à une autre |
Opérateurs logiques
Au nombre de 3, les opérateurs logiques permettent de tester la véracité d’un ensemble de conditions (AND
ou OR
) mais aussi d’en inverser la logique (NOT
).
Opérateur | Usage | Description |
---|---|---|
AND (&& ) | expr1 && expr2 | Renvoie true si toutes les comparaisons sont vraies ou false sinon |
OR (|| ) | expr1 || expr2 | Renvoie true si au moins l’une des comparaisons est vraie ou false sinon |
NOT (! ) | ! expr | Renvoie false si une comparaison est vraie ou renvoie true dans le cas contraire |
let dice = 1;
if (dice == 1) { // Ici, la condition renvoie "true"
// Il vaut mieux relancer le dé...
}
Il est également possible de combiner if
et else
dans une seule instruction pour ajouter des conditions intermédiaires.
let dice = 5;
if (dice == 1) {
// Il vaut mieux relancer le dé...
} else if (dice > 1 && dice <= 3) {
// C'est mieux...
} else if (dice > 3 && dice <= 5) {
// Pas mal !
}
Enfin, si aucune condition précédente n’est vérifiée, le mot-clé else
seul permet de déclencher un scénario alternatif.
let dice = 5;
if (dice == 1) {
// Il vaut mieux relancer le dé...
} else if (dice > 1 && dice <= 3) {
// C'est mieux...
} else if (dice > 3 && dice <= 5) {
// Pas mal !
} else {
// Super !
}
Conditions imbriquées
Il est bien évidemment possible d’imbriquer des conditions les unes dans les autres !
let note = 13;
if (note >= 0 && note <= 20) {
if (note >= 0 && note < 8) {
console.log("Refusé");
} else if (note >= 8 && note < 10) {
console.log("Rattrapage !");
} else if (note >= 10 && note < 12) {
console.log("Admis");
} else if (note >= 12 && note < 14) {
console.log("Admis avec mention AB");
} else if (note >= 14 && note <MdxCode 16) {
console.log("Admis avec mention B");
} else {
console.log("Admis avec mention TB");
}
} else {
console.log("Note non-valide");
}
switch
Dans l’écriture de raisonnements logiques similaires, le switch
propose une syntaxe alternative plus concise et plus lisible pour vérifier des égalités.
let fruit = "Banane";
switch (fruit) {
case 'Banane':
console.log(`${fruit} (1.93 € / kg)`);
break;
case 'Pomme':
console.log(`${fruit} (2.62 € / kg)`);
break;
case 'Mangue':
case 'Papaye':
console.log(`${fruit} (6.17 € / kg)`);
break;
default:
console.log(`Désolé, nous ne vendons pas de ${fruit}`);
}
switch (<valeur>)
: valeur à comparer dans les clausescase
.case exp
: expression à comparer avec la valeur de base.- Si correspondance, exécution d’une instruction
- Si non-correspondance, passage au
case
suivant
break
: spécifie la fin d’une instruction (bloccase
-break
)default
: clause exécutée par défaut si aucune correspondance n’est trouvée avec les clausescase
précédentes.
Boucles
Le principe des boucles est de répéter des instructions plusieurs fois.
for
La boucle for
(« pour ») est une boucle à nombre d’itérations fini. La variante forEach
en est une déclinaison fréquente et utile.
La boucle for
consiste à itérer en spécifiant 3 paramètres :
- Le point de départ
- Le point d’arrivée
- Le pas (« on va de x en x* »)
// Une boucle qui exécute 10 itérations en affichant à chaque tour 0, 1, 2, 3... 9
for (let i=0; i<10; i=i+1) {
console.log(i);
}
Au départ i
vaut 0, à chaque tour de boucle il s’incrémente de 1, et continue cela jusqu’à atteindre 9. Si nous avions écrit en point d’arrivée i<=10
, la boucle serait allée jusqu’à atteindre 10 et nous aurions donc effectué 11 tours de boucle.
Il est bien évidemment possible d’imbriquer des boucles les unes dans les autres !
forEach
La boucle forEach
(« pour chaque ») permet d’itérer sur les propriétés énumérables d’un objet (comme un tableau par exemple).
C’est la boucle utilisée lorsque vous voyez :
- Des articles listés sur un blog
- Des produits listés sur un site e-commerce
- Des utilisateurs listés sur un réseau social
- Des publications listées sur un feed de réseau social Bref, vous avez compris le principe. 😉
const languages = ["HTML", "CSS", "JavaScript", "PHP"];
languages.forEach(function(language) {
console.log(language); // Affiche "HTML", puis "CSS", etc.
});
Ici, language
prend successivement les valeurs du tableau languages
.
La méthode forEach()
exécute une fonction de callback récupérant successivement dans language
les valeurs du tableau languages
.
while
La boucle while
(« tant que ») est une boucle à nombre d’itérations non-défini.
La boucle while
est une sorte de mélange entre structure conditionnelle et structure itérative dans la mesure où on continue d’itérer tant qu’une condition est vérifiée.
while (password.length < 4) {
password = prompt("Ton mot de passe doit comporter au moins 4 caractères. Merci d'en saisir un nouveau.");
}
Fonctions
Les fonctions permettent de regrouper un ensemble d’instructions visant à résoudre une problématique au sein d’un même module. Il est possible de faire appel à un bloc de code de ce type afin qu’il effectue quelque chose et/ou nous retourne un résultat.
Fonctions natives
Comme tout langage de programmation, JavaScript ne déroge pas à la règle et vient avec son lot de fonctions natives. Il suffira alors de les appeler par leur nom.
let age = parseInt("43");
parseInt()
permet de convertir une chaîne de caractères en nombre entier. Si certaines fonctions comme parseInt()
sont dites globales (peuvent s’exécuter de « partout » dans le code), d’autres vont être associées à un contexte objet (un prototype), on parle de méthodes.
window.alert("Hello !"); // Affiche une pop-up textuelle
console.log("Hello !"); // Affiche un message dans la console
Math.random(); // Renvoie un nobre flottant aléatoire compris dans l'intervalle [0, 1[
Il en existe de nombreuses autres comme prompt()
, confirm()
, floor()
…
Fonctions custom
En JavaScript, il est possible de créer ses propres fonctions ; nous parlerons de fonctions « custom ».
Déclaration de fonction
Pour déclarer une fonction custom nous définissons :
- Son nom
- Des instructions
- (optionnels) Ses paramètres
- (optionnelle) Une valeur de retour (information retournée par la dite fonction)
Fonction avec nom
+ instructions
function nomFonction() {
// Instructions...
}
- On déclare systématiquement une fonction avec le mot-clé
function
- Le nom de la fonction est suivi de parenthèses
()
- Entre accolades
{
…}
, on écrit les instructions à exécuter par la fonction
Fonction avec nom
+ instructions
+ paramètres
+ valeur de retour
function nomFonction(param1, param2) {
// Instructions...
return ...
}
- Dans les parenthèses de la fonction
()
, on peut spécifier des paramètres (= informations transmises à la fonction) - Après le mot-clé
return
, on peut spécifier une valeur de retour (= information retournée par la fonction)
Appel de fonction
On fait appel à une fonction en spécifiant simplement son nom, suivi de parenthèses ()
.
functionName();
Si une fonction est définie avec des paramètres, il faudra alors lui transmettre des arguments.
functionName(arg1, arg2);
Quelques exemples
Ces 4 exemples illustrent les différents cas d’usage avec ou sans paramètres et valeurs de retour.
// ❌ pas de "return" / ❌ pas de paramètres
function sayHello1() {
console.log("Hello !");
}
// ✅ "return" / ❌ pas de paramètres
function sayHello2() {
return "Hello !";
}
// ❌ pas de "return" / ✅ paramètres
function sayHello3(firstname) {
console.log("Hello " + firstname + " !");
}
// ✅ "return" / ✅ paramètres
function sayHello4(firstname) {
return "Hello " + firstname + " !";
}
// Appels de fonction
sayHello1();
console.log(sayHello2());
sayHello3("Toto");
console.log(sayHello4("Toto"));
Cet exemple illustre quant à lui davantage l’intérêt d’une fonction dans un programme.
let user1 = { firstname: "Pierre", money: 1200 };
let user2 = { firstname: "Paul", money: 100 };
let user3 = { firstname: "Jacques", money: 1600 };
// La fonction va renvoyer "Virement effectué avec succès."
let payment1 = sendMoney(user1, user3, 200);
// La fonction va renvoyer "Paul n'a pas assez d'argent sur son compte !"
let payment2 = sendMoney(user2, user3, 200);
// Définition de la fonction
function sendMoney(transmitter, receiver, money) {
if (transmitter.money >= money) {
transmitter.money -= money;
receiver.money += money;
return "Virement effectué avec succès.";
} else {
return transmitter.firstname + " n'a pas assez d'argent sur son compte !";
}
}
Fonctions et objets
Il est tout à fait possible de définir une fonction au sein d’un objet. On parle alors de méthode.
const user = {
firstname: 'John',
lastname: 'Doe',
age: 30,
aboutMe: function() {
console.log(`Je m'appelle ${this.firstname} ${this.lastname} et j'ai ${this.age} ans.`);
}
};
user.aboutMe(); // Affiche "Je m'appelle John Doe et j'ai 30 ans."