Apprendre JS : Algorithmie

Variables, tableaux, conditions, boucles, fonctions... Découvrons la syntaxe de base de JavaScript pour écrire des algorithmes.

Icône de calendrier
Intermédiaire
8 chapitres

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)
copié !
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.

copié !
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.

copié !
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.

copié !
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] :

copié !
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 :

copié !
// 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 :

copié !
const objet = {
	cle1: valeur1,
	cle2: valeur2,
	// ...
};

Voici un exemple concret :

copié !
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'].

copié !
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é :

copié !
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 %.

copié !
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 +.

copié !
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}.

copié !
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érateurUsageDescription
==val1 == val2Teste une égalité (valeur)
===val1 === val2Teste une égalité stricte (valeur + type)
!=val1 != val2Teste une différence (valeur)
!==val1 !== val2Teste une différence stricte (valeur + type)
<val1 < val2Teste si une valeur est strictement inférieure à une autre
>val1 > val2Teste si une valeur est strictement supérieure à une autre
<=val1 <= val2Teste si une valeur est inférieure ou égale à une autre
>=val1 >= val2Teste 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érateurUsageDescription
AND (&&)expr1 && expr2Renvoie true si toutes les comparaisons sont vraies ou false sinon
OR (||)expr1 || expr2Renvoie true si au moins l’une des comparaisons est vraie ou false sinon
NOT (!)!exprRenvoie false si une comparaison est vraie ou renvoie true dans le cas contraire
copié !
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.

copié !
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.

copié !
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 !

copié !
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.

copié !
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 clauses case.
  • case exp : expression à comparer avec la valeur de base.
    1. Si correspondance, exécution d’une instruction
    2. Si non-correspondance, passage au case suivant
  • break : spécifie la fin d’une instruction (bloc case - break)
  • default : clause exécutée par défaut si aucune correspondance n’est trouvée avec les clauses case précédentes.

Boucles

Le principe des boucles est de répéter des instructions plusieurs fois.

for

La boucle forpour ») 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* »)
copié !
// 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 forEachpour 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. 😉
copié !
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 whiletant 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.

copié !
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.

copié !
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.

copié !
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 :

  1. Son nom
  2. Des instructions
  3. (optionnels) Ses paramètres
  4. (optionnelle) Une valeur de retour (information retournée par la dite fonction)
Fonction avec nom + instructions
copié !
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
copié !
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 ().

copié !
functionName();

Si une fonction est définie avec des paramètres, il faudra alors lui transmettre des arguments.

copié !
functionName(arg1, arg2);
Quelques exemples

Ces 4 exemples illustrent les différents cas d’usage avec ou sans paramètres et valeurs de retour.

copié !
// ❌ 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.

copié !
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.

copié !
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."