Baba Niang
252 FICHES · 27 CHAPITRES · 0 FRAMEWORK

JavaScriptGuide d’apprentissage et de révision

Baba Niang

Étudiant en Développement Back-End
à l’Institut Supérieur d’Enseignement Professionnel
de Diamniadio (ISEP)

252
FICHES
27
CHAPITRES
0
FRAMEWORK
01
Chapitre 015 fiches

Découvrir JavaScript

À quoi ça sert, comment ça tourne, premier script

JS · Fiche Originale

Fiche 1 — Qu'est-ce que JavaScript ?
💡 En clair

JavaScript est le langage qui donne vie aux pages web. Le HTML est le squelette, le CSS l'habillage, et JavaScript le cerveau : c'est lui qui réagit aux clics, change le contenu et fait des calculs.

📖 Mots à connaître
consolela zone où le code écrit ses messages. Dans le navigateur : appuie sur F12 puis clique sur l'onglet « Console ».
console.log(...)l'instruction la plus utilisée par les débutants : elle affiche ce que tu mets entre les parenthèses.
//un commentaire : le texte après // est ignoré par la machine. C'est écrit pour l'humain.
JS
console.log("Bonjour JavaScript !");
✏️ Ligne par ligne
// Afficher un messagecommentaire — jamais exécuté
console.log(...)affiche dans la console
"Bonjour JavaScript !"du texte (entre guillemets)
;termine l'instruction, comme un point final
Console
Bonjour JavaScript !
⚠️ Pièges fréquents
  • JS est sensible à la casse : console.log marche, Console.Log provoque une erreur.
  • Oublier les guillemets autour d'un texte (console.log(Bonjour)) → erreur : sans guillemets, JS cherche une variable nommée Bonjour.

JS · Fiche Originale

Fiche 2 — JavaScript, ECMAScript et moteur JavaScript
💡 En clair

Trois mots pour une seule idée : JavaScript est le langage que tu écris, ECMAScript est le cahier des charges officiel (les règles du jeu), et le moteur est le programme qui traduit et exécute ton code.

📖 Mots à connaître
ECMAScriptla norme officielle du langage (ex. « ECMAScript 2024 »). Grâce à elle, le même code fonctionne sur Chrome, Firefox et Edge.
Moteur JSle traducteur + exécutant. Chrome utilise V8, Firefox utilise SpiderMonkey.
Code machinele langage du processeur : uniquement des 0 et des 1. Ton code y est transformé avant d'être exécuté.
✏️ Ligne par ligne
1. Tu cris du codefichier .js, lisible par un humain
2. Le moteur le litV8, SpiderMonkey...
3. Il devient code machine0101 1100...
4. Résultat affichédans le navigateur ou sur un serveur
ℹ️ À savoir

Retiens l'image : le langage est une langue, la norme est le dictionnaire, le moteur est le traducteur.

JS · Fiche Originale

Fiche 3 — JavaScript dans le navigateur vs serveur
💡 En clair

Même langage, deux terrains de jeu : dans le navigateur (rendre les pages interactives) et sur un serveur avec Node.js (logique, fichiers, base de données).

📖 Mots à connaître
DOMla carte de ta page HTML que JS peut lire et modifier : changer un texte, cacher un bouton, ajouter une ligne...
Node.jsun programme qui exécute du JavaScript hors du navigateur, sur un ordinateur ou un serveur.
APIun service qu'un programme peut interroger (ex. récupérer la météo). fetch est l'outil JS pour appeler une API.
Frontend / Backendce que voit l'utilisateur (interface) / les coulisses (calculs, base de données).
🎯 Bon réflexe

Sécurité : le navigateur limite l'accès à ton ordinateur (pas de fichiers, pas de base de données). Node.js, lui, a un accès complet — c'est pour ça qu'il sert côté serveur.

ℹ️ À savoir

« SPA » (Single Page Application) = une page web qui se met à jour sans se recharger (Gmail, YouTube...).

JS · Fiche Originale

Fiche 4 — Premier programme JavaScript
💡 En clair

Le rituel de tout développeur : 1) écrire le code dans un fichier .js, 2) l'exécuter, 3) lire le résultat dans la console.

JS
// Ceci est un commentaire sur une ligne
console.log("Bonjour JavaScript !");
/*
C'est un commentaire
sur plusieurs lignes
*/
✏️ Ligne par ligne
// une lignecommente jusqu'à la fin de la ligne
/* ... */commente tout ce qui est entre les deux
console.log("...")affiche le message dans la console
Terminal
$ node monProgramme.js
Bonjour JavaScript !
📖 Mots à connaître
éditeur de codel'endroit où tu écris le code (VS Code est le plus utilisé).
terminalla fenêtre où tu tapes des commandes pour l'ordinateur.
nodela commande qui exécute un fichier .js avec Node.js.
⚠️ Pièges fréquents
  • Écrire le code ne suffit pas : il faut l'exécuter (node fichier.js) pour voir le résultat.
  • Si la commande node n'est pas trouvée, Node.js n'est pas installé sur la machine.

JS · Fiche Originale

Fiche 6 — defer et async
💡 En clair

Quand le navigateur lit ton HTML et rencontre une balise <script>, il peut tout arrêter pour exécuter le script. defer et async changent ce comportement.

📖 Mots à connaître
attributun mot ajouté dans la balise HTML pour modifier son comportement (ex. defer).
bloquer le HTMLle navigateur arrête d'afficher la page le temps de télécharger + exécuter le script → page blanche.
srcl'attribut qui indique quel fichier .js charger (ex. src="app.js").
✏️ Ligne par ligne
sans attributtélécharge ET exécute immédiatement → le HTML attend
defertélécharge en parallèle, exécute APRÈS le HTML, dans l'ordre
asynctélécharge en parallèle, exécute DÈS QU'IL EST PRÊT (ordre non garanti)
🎯 Bon réflexe

Ton script doit manipuler la page ? Utilise defer : le HTML est terminé, donc le DOM est prêt, et l'ordre des scripts est respecté.

02
Chapitre 026 fiches

Variables

let, const, var : stocker et nommer les valeurs

JS · Fiche Originale

Fiche 7 — Qu'est-ce qu'une variable ?
💡 En clair

Une variable est une boîte étiquetée : le nom est l'étiquette, la valeur est le contenu. Le symbole = ne veut pas dire « égal » mais « reçoit » : on met la valeur de droite dans la boîte de gauche.

JS
let nom = "Baba";
let age = 20;
let etudiant = true;
✏️ Ligne par ligne
letcrée la boîte
noml'étiquette (le nom de la variable)
=met la valeur dedans
"Baba"la valeur — du texte, donc entre guillemets
20un nombre : jamais de guillemets
trueun booléen (vrai) : jamais de guillemets
Console
nom → "Baba"
age → 20
etudiant → true
🔍 Ce que fait le code

Pour voir ce résultat toi-même, ajoute console.log(nom) : la console affiche la valeur actuelle de la boîte.

⚠️ Pièges fréquents
  • Le texte a besoin de guillemets, pas les nombres ni true/false.
  • La valeur peut changer plus tard « selon le mot-clé » : c'est le sujet des fiches let / const / var.

JS · Fiche Originale

Fiche 8 — let
💡 En clair

let déclare une variable dont la valeur peut être remplacée plus tard. C'est le choix par défaut quand la valeur doit évoluer (un score, un compteur...).

JS
let compteur = 10;
compteur = 25;
console.log(compteur);
✏️ Ligne par ligne
let compteur = 10;DÉCLARATION : on crée la boîte avec 10 dedans
compteur = 25;RÉAFFECTATION : on remplace le contenu (sans let !)
console.log(compteur);affiche la valeur ACTUELLE
Console
25
⚠️ Pièges fréquents
  • Ne remets pas let pour changer une valeur : let compteur = 25; recréerait une variable. Une seule déclaration, ensuite juste compteur = ....
  • « À privilégier dans la majorité des cas » = dès que la valeur va changer. Sinon, pense const (fiche suivante).

JS · Fiche Originale

Fiche 9 — const
💡 En clair

const crée une constante : la valeur est posée une fois pour toutes. Toute tentative de remplacement déclenche une erreur.

JS
const PI = 3.14;
const nom = "Baba";
console.log(PI);
console.log(nom);
Console
3.14
Baba
JS
const nom = "Baba";
nom = "Niang";
Erreur
TypeError: Assignment to constant variable.
at exemple.js:2
🔍 Ce que fait le code

Le message d'erreur exact est TypeError: Assignment to constant variable : JS refuse de réassigner une constante. La ligne fautive est indiquée à la fin du message.

📖 Mots à connaître
réassignerremplacer la valeur par une autre avec =. Seule la réassignation est bloquée par const.
MAJUSCULEShabitude courante : les constantes « connues » s'écrivent en majuscules (PI, TAUX_TVA) pour les repérer d'un coup d'œil.
⚠️ Pièges fréquents
  • Subtilité importante : const empêche de remplacer la valeur, mais ne fige pas le contenu d'un tableau ou d'un objet (tu le verras avec les objets).
  • Oublier d'initialiser (const x;) est une erreur : une constante doit recevoir sa valeur dès sa création.

JS · Fiche Originale

Fiche 10 — var
💡 En clair

var est la façon historique (avant 2015) de déclarer une variable. Ça fonctionne encore, mais le JavaScript moderne utilise let et const.

JS
var nom = "Baba";
var age = 20;
console.log(nom);
console.log(age);
🔍 Ce que fait le code

Pourquoi éviter ? var a des règles de portée anciennes et surprenantes qui provoquent des bugs difficiles à trouver. let et const ont des règles plus saines — tu les croiseras dans tout code récent.

🎯 Bon réflexe

Lis var dans du vieux code → comprends-le comme let. Mais dans TON code, écris const ou let.

JS · Fiche Originale

Fiche 11 — let vs const vs var
💡 En clair

Les trois créent des variables. La différence tient en une question : « cette valeur va-t-elle changer ? »

JS
let age = 10;
age = 20;
console.log(age);
Console
20
JS
const PI = 3.14;
// PI = 3.5;  // Erreur !
console.log(PI);
Console
3.14
JS
var score = 10;
score = 20;
console.log(score);
Console
20
✏️ Ligne par ligne
let → valeur modifiable
const → valeur non modifiable (erreur si tu réassignes)
var → ancienne façon : à éviter dans un nouveau code
🎯 Bon réflexe

Réflexe pro : écris const partout par défaut. Si tu te retrouves bloqué (la valeur DOIT changer), remplace par let. Ton code devient plus sûr.

JS · Fiche Originale

Fiche 12 — Règles de nommage
💡 En clair

Un nom valide doit commencer par une lettre, _ ou $, ne contenir que lettres/chiffres/_/$, sans espace, et ne pas être un mot réservé.

📖 Mots à connaître
mot réservéun mot déjà pris par le langage : let, if, for... Interdit comme nom de variable.
camelCasepremier mot en minuscule, chaque mot suivant commence par une majuscule : nomEtudiant, prixTotal.
casseJS distingue majuscules et minuscules : age et Age sont DEUX variables différentes.
✏️ Ligne par ligne
let nom = ...✗ interdit : commence par un chiffre
let mon nom = ...✗ interdit : espace dans le nom
let prix-total = ...✗ interdit : le « - » est une soustraction pour JS
let @age = ...✗ interdit : @ n'est pas autorisé
let let = 5;✗ interdit : let est un mot réservé
🎯 Bon réflexe

Nom explicite = nom qui se lit comme une phrase : nombreCours plutôt que nb. Dans 6 mois, tu remercieras ton « toi » du présent.

03
Chapitre 037 fiches

Types de données

string, number, boolean et les autres

JS · Fiche Originale

Fiche 13A — Types primitifs : vue d'ensemble
💡 En clair

Un type est la nature d'une valeur : texte, nombre, vrai/faux... JavaScript possède 7 types primitifs — des valeurs simples, prêtes à l'emploi.

📖 Mots à connaître
primitifune valeur simple et de base (un nombre, un texte...), par opposition aux objets qui sont des ensembles de valeurs.
immuableon ne modifie jamais la valeur d'origine : on en crée une nouvelle. Ex. mettre un texte en majuscules crée un NOUVEAU texte.
déclarer / initialisercréer la variable (let x) / lui donner sa première valeur (= 42).
✏️ Ligne par ligne
let n = 42;number — entier ou décimal
let nom = "Baba";string — du texte, entre guillemets
let actif = true;boolean — vrai ou faux
let x;undefined — déclarée mais jamais remplie
let user = null;null — vide VOLONTAIREMENT
let id = Symbol("id");symbol — identifiant unique
let grand = 9007n;bigint — entier géant (n à la fin)
🎯 Bon réflexe

Les guillemets simples 'Bonjour' et doubles "Bonjour" sont équivalents en JS. Choisis-en un et garde-le.

JS · Fiche Originale

Fiche 13B — string, number, boolean
💡 En clair

Ce sont les trois types que tu utiliseras 95 % du temps : texte, nombre, et vrai/faux.

📖 Mots à connaître
stringdu texte, TOUJOURS entouré : ' ', " " ou backticks ``.
numberun nombre, SANS guillemets. Entier (20) ou décimal (99.5) — avec un point, jamais de virgule.
booleantrue ou false, sans guillemets. La réponse à une question oui/non.
JS
let nom = "Baba";
let message = 'Salut';
let titre = `Étudiant`;
Console
20
99.5
-10
⚠️ Pièges fréquents
  • Décimaux avec un point : 3.14 ✅ — 3,14 ❌ (la virgule a une autre signification en JS).
  • "20" avec guillemets est un TEXTE, pas un nombre : tu ne peux pas additionner proprement dessus (fiches 20 et 57 pour comprendre).

JS · Fiche Originale

Fiche 13C — undefined et null
💡 En clair

Deux façons de dire « pas de valeur » : undefined = pas encore remplie (JS le fait tout seul), null = vidée exprès (c'est TOI qui le décides).

JS
let x;
console.log(x);
// undefined
Console
undefined
JS
let user = null;
console.log(user);
// null
Console
null
✏️ Ligne par ligne
let x;la boîte existe mais JS y met undefined automatiquement
let user = null;TU décides que la boîte est vide (ex. « pas encore connecté »)
🎯 Bon réflexe

Image à retenir : undefined = boîte jamais remplie. null = boîte qu'on a vidée exprès.

⚠️ Pièges fréquents
  • undefined et null ne sont PAS égales strictement : undefined === null vaut false (fiche 20 pour ===).
  • Une fonction qui ne renvoie rien renvoie... undefined.

JS · Fiche Originale

Fiche 13D — bigint et symbol
💡 En clair

Deux types rares : bigint pour des entiers gigantesques (on colle un n à la fin), symbol pour créer un identifiant garanti unique.

📖 Mots à connaître
Number.MAX_SAFE_INTEGERle plus grand entier « sûr » : 9 007 199 254 740 991. Au-delà, les calculs perdent en précision → passe en bigint.
immuableun symbol ne peut pas être modifié une fois créé.
clé d'objetl'étiquette d'une case dans un objet. Symbol sert à créer des étiquettes qui ne risquent pas d'entrer en collision.
JS
let id1 = Symbol("id");
let id2 = Symbol("id");
console.log(id1 === id2);
// false
Console
false
🔍 Ce que fait le code

Même étiquette "id", mais chaque Symbol() crée une valeur unique : les deux symbols ne sont jamais égaux. C'est justement leur utilité.

ℹ️ À savoir

Tu n'en verras pas tous les jours. Retiens simplement : n à la fin = bigint, Symbol() = unique à chaque appel.

JS · Fiche Originale

Fiche 14 — typeof
💡 En clair

typeof répond à la question « quel est le type de cette valeur ? » — et renvoie la réponse sous forme de texte (avec des guillemets).

JS
console.log(typeof 42);        // "number"
console.log(typeof "Bonjour"); // "string"
console.log(typeof true);      // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof null);      // "object" (!)
console.log(typeof []);        // "object"
console.log(typeof function() {}); // "function"
Console
"number"
"string"
"boolean"
"undefined"
"object"
"object"
"function"
🔍 Ce que fait le code

Utilisation réelle : tester une valeur avant de s'en servir — if (typeof age === "number") { ... }. Ça évite de faire un calcul sur du texte.

⚠️ Pièges fréquents
  • typeof null → "object" est un bug historique jamais corrigé (pour ne pas casser les anciens sites). null n'est PAS un objet.
  • typeof [] → "object" aussi : pour savoir si une valeur est un tableau, utilise Array.isArray([]) → true.
  • typeof renvoie du TEXTE : compare avec des guillemets — typeof 42 === "number", pas === number.

JS · Fiche Originale

Fiche 15 — Valeurs primitives vs objets
💡 En clair

Les primitifs sont des valeurs simples : on les copie comme une photo. Les objets sont des valeurs complexes : on les partage comme un lien.

JS
let a = 10;
let b = a;      // b reçoit une COPIE de 10
b = 20;
console.log(a); // 10 (a n'a pas changé)
Console
10
JS
let obj1 = { nom: "Baba" };
let obj2 = obj1;        // obj2 pointe vers le MÊME objet
obj2.nom = "Niang";
console.log(obj1.nom);  // "Niang" (modifié !)
Console
"Niang"
🔍 Ce que fait le code

La ligne { nom: "Baba" } crée un objet : une collection avec une case nom. Quand tu copies obj2 = obj1, tu copies l'ADRESSE de l'objet, pas son contenu : les deux variables regardent le même objet.

📖 Mots à connaître
mutable / immuablemodifiable / non modifiable. Les primitifs sont immuables, les objets mutables.
référencel'adresse où l'objet vit en mémoire.
🎯 Bon réflexe

Pour copier VRAIMENT un objet : const copie = { ...original }. Tu verras ça en détail avec les objets.

JS · Fiche Originale

Fiche 16 — Valeur vs référence
💡 En clair

La règle d'or : primitif → on copie la VALEUR (deux boîtes indépendantes). Objet → on copie la RÉFÉRENCE (une seule boîte, deux étiquettes).

JS
let a = 10;
let b = a;
b = 20;
console.log(a); // 10
console.log(b); // 20
Console
10
20
JS
let obj1 = { nom: "Baba" };
let obj2 = obj1;
obj2.nom = "Niang";
console.log(obj1.nom); // "Niang"
console.log(obj2.nom); // "Niang"
Console
"Niang"
"Niang"
✏️ Ligne par ligne
let b = a;b reçoit une copie indépendante de 10
let obj2 = obj1;obj2 reçoit l'adresse du même objet
obj2.nom = "Niang";on modifie l'objet UNIQUE → visible par obj1 aussi
⚠️ Pièges fréquents
  • Piège classique : modifier obj2 change aussi obj1 — ce n'est pas un bug JS, c'est le même objet.
  • Cette règle explique pourquoi les fonctions peuvent modifier un objet passé en argument (plus tard dans ton apprentissage).
04
Chapitre 0413 fiches

Opérateurs

Calculer, comparer, combiner

JS · Fiche Originale

Fiche 17 — Opérateurs arithmétiques
💡 En clair

Les six opérateurs du calcul : + - * / % (reste) et ** (puissance).

📖 Mots à connaître
% modulole RESTE de la division. 10 % 3 : 10 = 3×3 + 1 → 1. Sert surtout à tester si un nombre est pair : n % 2 === 0.
** puissance2 ** 3 = 2 × 2 × 2 = 8.
JS
let a = 10;
let b = 3;
console.log(a + b);  // 13
console.log(a - b);  // 7
console.log(a * b);  // 30
console.log(a / b);  // 3.3333333333333335
console.log(a % b);  // 1
console.log(a ** b); // 1000
Console
13
7
30
3.3333333333333335
1
1000
⚠️ Pièges fréquents
  • La fiche écrit 3.333... : en vrai la console affiche 3.3333333333333335 — les décimaux sont arrondis par l'ordinateur (fiche 62-V).
  • / donne toujours un nombre décimal possible : 10 / 2 → 5, même si c'est un entier.
  • Piège du + : sur du texte, il COLLE les chaînes. "5" + 5 → "55" !

JS · Fiche Originale

Fiche 18 — ++ et --
💡 En clair

x++ augmente de 1, x-- diminue de 1. C'est le raccourci de x = x + 1 — l'opération la plus courante du monde des boucles.

✏️ Ligne par ligne
x++équivaut à x = x + 1
x--équivaut à x = x - 1
++x (préfixe)augmente D'ABORD, puis renvoie la nouvelle valeur
x++ (postfixe)renvoie D'ABORD l'ancienne valeur, puis augmente
JS
let y = 5;
console.log(y++); // 5 (renvoie avant d'augmenter)
console.log(y);   // 6
Console
5
6
JS
let x = 5;
console.log(++x); // 6 (augmente avant de renvoyer)
Console
6
⚠️ Pièges fréquents
  • console.log(y++) affiche l'ANCIENNE valeur — piège classique en lecture de code.
  • En dehors des boucles, préfère l'écriture claire : x = x + 1 ou x += 1.

JS · Fiche Originale

Fiche 19 — Opérateurs d'affectation
💡 En clair

Les opérateurs composés modifient la variable ET affectent en un seul geste : x += 5 est le raccourci de x = x + 5.

JS
let x = 10;   // 10
x += 5;       // 15
x -= 3;       // 12
x *= 2;       // 24
x /= 4;       // 6
x %= 3;       // 0
Console
15
12
24
6
0
✏️ Ligne par ligne
x += 5équivaut à x = x + 5
x %= 3équivaut à x = x % 3 — ici 6 % 3 → 0
🔍 Ce que fait le code

La fiche enchaîne les opérations : chaque ligne part du résultat de la précédente (10 → 15 → 12 → 24 → 6 → 0). Suis la valeur de x ligne par ligne.

JS
let message = "Hello";
message += " World";
console.log(message);
Console
Hello World
⚠️ Pièges fréquents
  • Ce raccourci marche aussi sur les textes : += COLLE la chaîne (on dit « concaténer »).
  • = affecte, === compare — la confusion entre les deux dans un if est un bug très fréquent (fiches 20 et 31).

JS · Fiche Originale

Fiche 20 — == VS ===
💡 En clair

=== compare valeur ET type (stricte, recommandée). == compare après avoir converti les types (surprenante, à éviter).

JS
5 == "5"   // true  : "5" converti en 5
5 === "5"  // false : number vs string

0 == false   // true
0 === false  // false

null == undefined   // true (cas spécial)
null === undefined  // false
Console
true
false
true
false
true
false
🔍 Ce que fait le code

Avec ==, JS transforme automatiquement un type en un autre avant de comparer (on appelle ça la conversion ou coercition). Avec ===, si les types diffèrent, la réponse est directement false — aucune conversion.

📖 Mots à connaître
conversion (coercition)JS change un type en un autre tout seul : "5" devient 5 pour permettre la comparaison.
⚠️ Pièges fréquents
  • Règle de survie : utilise TOUJOURS ===. Tu sais exactement ce qui est comparé.
  • [] == false est true (le tableau vide devient 0) — personne ne veut ce genre de surprise.
  • NaN === NaN est false, même avec === (fiche 55).

JS · Fiche Originale

Fiche 21 — != VS !==
💡 En clair

Ce sont les contraires de la fiche précédente : != (laxique) et !== (strict, recommandé). !== répond « est-ce que c'est DIFFÉRENT en valeur OU en type ? ».

JS
5 !== "5"          // true : types différents
0 !== false        // true
null !== undefined // true
"0" !== 0          // true
Console
true
true
true
true
JS
// Usage typique : une saisie non vide ?
let saisie = "Baba";
if (saisie !== "") {
  console.log("Merci " + saisie);
}
Console
Merci Baba
🔍 Ce que fait le code

Lecture de 5 !== "5" : 5 est un number, "5" est une string → types différents → ils sont strictement différents → true.

⚠️ Pièges fréquents
  • ⚠️ Correction de la fiche : la ligne [] != false; // true est erronée. Teste par toi-même : [] != false affiche false (car [] == false est true, le tableau vide est converti en 0). Tout le reste du tableau de la fiche est juste — et ça démontre encore pourquoi il faut === et !== !
  • Mémo : != est le contraire de ==, !== est le contraire de ===.

JS · Fiche Originale

Fiche 22 — && (ET logique)
💡 En clair

&& veut dire « ET » : le résultat est vrai seulement si TOUTES les conditions sont vraies.

JS
let a = 5;
let b = 10;
console.log(a > 0 && b > 0); // true
Console
true
✏️ Ligne par ligne
true && true→ true
true && false→ false
false && (peu importe)→ false
🔍 Ce que fait le code

Court-circuit : si la première condition est fausse, JS ne regarde même pas la deuxième — le résultat est déjà connu (false).

🎯 Bon réflexe

Usage type : if (age >= 18 && aLePermis) { ... } — les deux doivent être vrais pour conduire.

JS · Fiche Originale

Fiche 23 — || (OU logique)
💡 En clair

|| veut dire « OU » : le résultat est vrai dès que au moins une condition est vraie.

JS
let a = 5;
let b = 0;
console.log(a > 0 || b > 0); // true
Console
true
✏️ Ligne par ligne
true || false→ true
false || true→ true
false || false→ false
🔍 Ce que fait le code

Court-circuit aussi : si la première condition est vraie, la seconde n'est pas évaluée.

🎯 Bon réflexe

Un usage très courant : valeur par défaut — const nom = saisie || "Anonyme". Si saisie est vide (falsy), on prend "Anonyme". Tu comprendras le pourquoi avec truthy/falsy (fiche 25).

JS · Fiche Originale

Fiche 24 — ! (NON logique)
💡 En clair

! inverse la valeur : vrai devient faux, faux devient vrai. Double inverser (!!) ramène n'importe quelle valeur à un vrai booléen.

JS
let a = true;
console.log(!a);        // false

let age = 20;
console.log(!(age > 18)); // false
Console
false
false
✏️ Ligne par ligne
!true→ false
!false→ true
!!valeurconvertit valeur en booléen (truthy → true)
🔍 Ce que fait le code

Dans !(age > 18), le ! s'applique au RÉSULTAT de la comparaison : age > 18 vaut true, donc ! donne false.

ℹ️ À savoir

La fiche montre function estVide(tab) { return tab.length === 0; } : une fonction (bloc réutilisable) qui teste si un tableau est vide. Les fonctions arrivent plus loin dans ton parcours.

JS · Fiche Originale

Fiche 25 — Truthy et falsy
💡 En clair

Dans une condition, JS convertit chaque valeur en booléen. Les 8 valeurs falsy deviennent false, tout le reste est truthy.

✏️ Ligne par ligne
falsefalsy — évidemment
0 et -0falsy — le zéro
0nfalsy — BigInt zéro
""falsy — chaîne VIDE (sans espace)
nullfalsy
undefinedfalsy
NaNfalsy
Tout le restetruthy : 42, "0", " ", [], {}, function...
JS
if (0) {
  console.log("ne s'affiche pas");   // 0 est falsy
}
if ("Bonjour") {
  console.log("s'affiche");          // chaîne non vide
}
if ([]) {
  console.log("s'affiche aussi");    // tableau vide = truthy !
}
Console
s'affiche
s'affiche aussi
⚠️ Pièges fréquents
  • Piège n°1 : "0", "false" et " " (avec espace) sont des chaînes NON vides → truthy !
  • Un tableau ou un objet, même vide, est truthy. Seules les 8 valeurs listées sont falsy.
🎯 Bon réflexe

Pour tester la conversion toi-même : console.log(Boolean("0")) → true.

JS · Fiche Originale

Fiche 27 — Opérateur ?? (Nullish coalescing)
💡 En clair

?? se lit : « prends la valeur de gauche, sauf si elle vaut null ou undefined — dans ce cas prends celle de droite ». « Nullish » = null ou undefined.

JS
let pseudo = null;
console.log(pseudo ?? "Invité");   // "Invité"

let score = 0;
console.log(score ?? 100);         // 0 (pas remplacé !)
Console
"Invité"
0
🔍 Ce que fait le code

C'est le raccourci du bloc if/else montré sur la fiche : si la valeur de gauche n'est ni null ni undefined, on la garde ; sinon on prend celle de droite.

⚠️ Pièges fréquents
  • Interdit de mélanger ?? avec || ou && sans parenthèses → SyntaxError.
  • Le nom complet « Nullish coalescing operator » se traduit par : « fusion avec null ».

JS · Fiche Originale

Fiche 28 — Optional chaining ?.
💡 En clair

?. se lit « avance prudemment » : si la partie de gauche est null ou undefined, JS renvoie undefined au lieu de planter.

JS
const user = null;

console.log(user.nom);           // ❌ TypeError !
console.log(user?.nom);          // ✅ undefined
Console
TypeError: Cannot read properties of null (reading 'nom')
undefined
📖 Mots à connaître
TypeErrorl'erreur « impossible de lire une propriété de null ». Elle ARRÊTE le script — le crash le plus fréquent chez le débutant.
chaînageon peut enchaîner : user?.adresse?.ville — dès qu'un maillon est null/undefined, tout donne undefined.
✏️ Ligne par ligne
obj?.proplecture d'une propriété, sans risque
obj?.[cle]lecture avec une clé variable (crochets)
obj?.methode()appel d'une méthode, seulement si elle existe
🎯 Bon réflexe

À utiliser quand une donnée peut manquer (réponse d'API, champ optionnel). Mais n'en mets pas partout : ?., c'est « je m'attends à ce que ça manque ».

JS · Fiche Originale

Fiche 29 — ?? vs ||
💡 En clair

Les deux donnent une valeur de secours, mais pas au même moment : || remplace dès que la valeur est falsy (0, "", false...) ; ?? remplace uniquement sur null / undefined.

JS
let b = 0;
console.log(b ?? 100);  // 0   : 0 est une vraie valeur
console.log(b || 100);  // 100 : 0 est falsy → remplacé

let c = "";
console.log(c ?? "Aucun"); // ""
console.log(c || "Aucun"); // "Aucun"
Console
0
100
""
"Aucun"
✏️ Ligne par ligne
??sécurisé : garde 0, "" et false (utile pour un compteur, un prix, un toggle)
||général : remplace toute valeur falsy (pratique pour une saisie vide)
🎯 Bon réflexe

Question à te poser : est-ce que 0, "" ou false sont des valeurs LÉGITIMES dans mon cas ? Si oui → ??.

ℹ️ À savoir

La fiche imprime "Invite" sans accent dans le code et "Invité" dans les commentaires : c'est le même mot, l'intention est "Invité".

JS · Fiche Originale

Fiche 30 — Priorité des opérateurs
💡 En clair

Comme en mathématiques : la multiplication se fait avant l'addition, et les parenthèses gagnent toujours.

JS
console.log(10 + 5 * 2);   // 20 : 5 * 2 d'abord
console.log((10 + 5) * 2); // 30 : les parenthèses d'abord
Console
20
30
✏️ Ligne par ligne
( )niveau 1 — toujours gagnant
* / %avant + -
< > <= >=avant == === !=
&&avant ||
=le dernier : l'affectation arrive toujours à la fin
🔍 Ce que fait le code

Lecture de 10 + 5 > 12 && true : calcul (15 > 12) → true, puis true && true → true.

🎯 Bon réflexe

En cas de doute, mets des parenthèses : c'est gratuit, ça change rien au résultat voulu, et ça rend ton code lisible pour les autres.

05
Chapitre 052 fiches

Conditions

if et switch : décider dans le code

JS · Fiche Originale

Fiche 31 — Instruction if
💡 En clair

if = « SI la condition est vraie, exécute ce bloc ». else = « SINON ». else if = « SINON, SI ».

JS
let age = 20;

if (age >= 18) {
  console.log("Majeur");
} else {
  console.log("Mineur");
}
Console
Majeur
JS
let note = 14;

if (note >= 16) {
  console.log("Très bien");
} else if (note >= 10) {
  console.log("Bien");
} else {
  console.log("Insuffisant");
}
Console
Bien
✏️ Ligne par ligne
if (condition)la condition devient true ou false
{ ... }le bloc exécuté seulement si true
else if / elsetestés seulement si les précédents ont échoué
🔍 Ce que fait le code

JS lit les conditions de HAUT en BAS et s'arrête au premier vrai : ordonne donc tes tests du plus restrictif au plus général.

⚠️ Pièges fréquents
  • La condition peut être n'importe quelle valeur : if (nom) est vrai si nom est truthy (fiche 25).
  • Pas de ; après if (cond) { } — et l'indentation (le décalage) ne change rien à l'exécution, elle sert uniquement à lire.

JS · Fiche Originale

Fiche 34 — Instruction switch
💡 En clair

switch compare une valeur à une liste de cas. C'est une alternative propre à une longue suite de else if quand on compare toujours la même valeur à des valeurs exactes.

JS
const jour = "lundi";

switch (jour) {
  case "lundi":
    console.log("Début de semaine");
    break;
  case "vendredi":
    console.log("Bientôt le week-end");
    break;
  default:
    console.log("Jour inconnu");
}
Console
Début de semaine
✏️ Ligne par ligne
switch (jour)la valeur à tester
case "lundi":est-ce que jour === "lundi" ?
break;SORT du switch (sinon on continue dans le cas suivant !)
default:le cas « aucun ne correspond »
🔍 Ce que fait le code

Le break est vital : sans lui, l'exécution « tombe » dans le cas suivant (c'est le fall-through). Oublier un break est LE bug classique du switch.

⚠️ Pièges fréquents
  • switch utilise === (égalité stricte) : case "1" ne matchera pas le nombre 1.
  • Pour des plages de valeurs (age >= 18), reste sur if / else if.
06
Chapitre 068 fiches

Boucles

while, do...while, for...of, for...in

JS · Fiche Originale

Fiche 35 — Boucle while
💡 En clair

while = « TANT QUE la condition est vraie, répète le bloc ». La condition est testée avant chaque tour.

JS
let i = 1;

while (i <= 5) {
  console.log("Itération :", i);
  i = i + 1;   // ou i++
}
Console
Itération : 1
Itération : 2
Itération : 3
Itération : 4
Itération : 5
✏️ Ligne par ligne
let i = 1;le compteur, déclaré avant la boucle
while (i <= 5)continue tant que c'est vrai
i = i + 1;augmente le compteur — INDISPENSABLE
console.log("Itération :", i)la virgule affiche les deux valeurs séparées par un espace
🔍 Ce que fait le code

Déroule mentalement : i vaut 1 → condition vraie → affiche → i devient 2 → ... → i vaut 6 → condition fausse → la boucle s'arrête.

⚠️ Pièges fréquents
  • Oublie l'incrémentation → condition toujours vraie → boucle infinie : le programme gèle. C'est LE piège de while.
  • Si la condition est fausse dès le départ, le bloc ne s'exécute jamais.

JS · Fiche Originale

Fiche 36 — Boucle do...while
💡 En clair

do...while exécute le bloc au moins une fois, PUIS teste la condition. La seule différence avec while est l'ordre : test avant vs test après.

JS
let i = 1;

do {
  console.log("Tour numéro :", i);
  i++;
} while (i <= 3);
Console
Tour numéro : 1
Tour numéro : 2
Tour numéro : 3
✏️ Ligne par ligne
whileteste AVANT → le bloc peut ne jamais s'exécuter
do...whileteste APRÈS → le bloc tourne au moins une fois
⚠️ Pièges fréquents
  • Le point-virgule final est obligatoire : } while (condition);
  • Usage typique : reposer une question à l'utilisateur jusqu'à obtenir une réponse valide — on doit bien poser la question une première fois.

JS · Fiche Originale

Fiche 39-V — Cycle d'une boucle
💡 En clair

Cette fiche complémentaire démonte le moteur d'une boucle for : un cycle immuable à 4 étapes qui se répète jusqu'à ce que la condition devienne fausse.

JS
for (let i = 0; i < 3; i++) {
  console.log("Itération :", i);
}
Console
Itération : 0
Itération : 1
Itération : 2
✏️ Ligne par ligne
let i = 0INITIALISATION — exécutée une seule fois au début
i < 3CONDITION — testée avant chaque tour : vraie → on exécute le corps
console.log(...)CORPS — le bloc d'instructions de chaque itération
i++INCRÉMENT — modifie le compteur, puis retour à la condition
🔍 Ce que fait le code

Le tableau de la fiche suit tout le cycle : i=0 (vraie → affiche 0), i=1 (vraie → affiche 1), i=2 (vraie → affiche 2), i=3 (FAUSSE → sortie de boucle).

⚠️ Pièges fréquents
  • Si la condition est fausse dès le départ, le corps ne s'exécute JAMAIS.
  • L'ordre est fixe : initialisation → condition → corps → incrément → condition → ...

JS · Fiche Originale

Fiche 40 — for...of
💡 En clair

for...of parcourt les VALEURS d'une collection, une par une, sans compteur ni index à gérer.

📖 Mots à connaître
itérablequelque chose qu'on peut parcourir élément par élément : tableau, chaîne, Set, Map...
Setune collection de valeurs uniques. new Set([1, 2, 3]) en crée une.
Mapune collection de paires clé → valeur.
JS
const fruits = ["Pomme", "Banane", "Orange"];

for (const fruit of fruits) {
  console.log(fruit);
}
Console
Pomme
Banane
Orange
JS
for (const lettre of "JS") {
  console.log(lettre);
}
Console
J
S
⚠️ Pièges fréquents
  • Pourquoi const dans la boucle ? La variable est recréée à chaque tour : elle n'est jamais réassignée, donc const est valide et recommandé.
  • for...of ne fonctionne PAS sur un objet classique — pour ça, voir for...in (fiche suivante).

JS · Fiche Originale

Fiche 41 — for...in
💡 En clair

for...in parcourt les CLÉS d'un objet : les noms de propriétés (ou les index d'un tableau).

JS
const etudiant = {
  nom: "Baba",
  age: 20,
  "filière": "Développement"
};

for (const clé in etudiant) {
  console.log(clé, ":", etudiant[clé]);
}
Console
nom : Baba
age : 20
filière : Développement
✏️ Ligne par ligne
{ nom: "Baba" }un objet littéral : des paires clé: valeur
const cléreçoit à chaque tour le NOM d'une propriété (un texte)
etudiant[clé]accès par crochets : obligatoire quand la clé est dans une variable
🔍 Ce que fait le code

La syntaxe etudiant[clé] se lit « la propriété dont le nom est contenu dans clé ». Les crochets acceptent une variable, le point non.

⚠️ Pièges fréquents
  • Les clés sont des chaînes de caractères (même pour un tableau : "0", "1"...).
  • Sur un tableau, préfère for...of : il donne directement les valeurs, dans l'ordre.

JS · Fiche Originale

Fiche 42 — for...of vs for...in
💡 En clair

Le duel résumé : for...of sort les valeurs, for...in sort les clés. Même tableau, deux regards.

JS
const fruits = ["Pomme", "Banane", "Orange"];

for (const fruit of fruits) {
  console.log(fruit);   // la VALEUR
}

for (const index in fruits) {
  console.log(index);   // la CLÉ (index)
}
Console
Pomme
Banane
Orange
0
1
2
✏️ Ligne par ligne
for...of →les valeurs : "Pomme", "Banane"...
for...in →les clés : 0, 1, 2 (en réalité des chaînes "0", "1"...)
🎯 Bon réflexe

Mémo visuel de la fiche : of sort le contenu des cases, in sort les étiquettes des cases. Pour un tableau : of. Pour un objet : in.

JS · Fiche Originale

Fiche 42-2 — for...of vs for...in — avec un objet
💡 En clair

La même comparaison appliquée à un objet : for...in liste ses clés (nom, age, filiere), alors que for...of refuse les objets classiques.

JS
const etudiant = {
  nom: "Baba",
  age: 20,
  filiere: "Développement"
};

for (const clé in etudiant) {
  console.log(clé);   // nom, age, filiere
}
Console
nom
age
filiere
⚠️ Pièges fréquents
  • for...of sur un objet classique → TypeError: etudiant is not iterable. Retiens l'erreur : un objet n'est pas itérable.
  • « Ordre des clés non garanti » : pour les clés textuelles, JS ne promet pas leur ordre de parcours — ne t'y fie pas.
🎯 Bon réflexe

Règle des pros : of pour parcourir des éléments, in pour inspecter des propriétés.

JS · Fiche Originale

Fiche 42-V — for...of vs for...in — Schémas visuels
💡 En clair

Cette fiche 100 % visuelle grave l'image mentale : le tableau est une rangée de cases, chacune avec son index (0, 1, 2) et sa valeur ("Pomme"...).

✏️ Ligne par ligne
for...offlèche vers les VALEURS : "Pomme", "Banane", "Orange"
for...inflèche vers les INDEX : 0, 1, 2
🔍 Ce que fait le code

Reprends le schéma de la fiche : le tableau itérable est à gauche, la boucle au centre, et à droite ce que la boucle fait sortir — les cases (of) ou les étiquettes (in).

ℹ️ À savoir

Les couleurs des cases sur le schéma sont décoratives : elles aident juste à voir les 3 éléments distincts.

07
Chapitre 0712 fiches

Chaînes de caractères

créer, découper, chercher, remplacer

JS · Fiche Originale

Fiche 43 — Créer une chaîne
💡 En clair

Une chaîne (string) est du texte. Trois paires de guillemets sont valides : ' ', " " et `` (backticks). Le contenu, lui, ne change pas : une chaîne se crée, se lit, se découpe — mais jamais ne se modifie sur place.

JS
const nom = "Baba";
const ville = 'Dakar';
const phrase = `Salut le monde`;
⚠️ Pièges fréquents
  • Guillemets imbriqués : "J\'aime JS" ❌ mais "J'aime JS" ✅ (apostrophe dans des doubles) ou 'Il a dit "salut"' ✅.
  • Le backtick se trouve sur la touche ` (souvent à gauche du 1, avec AltGr selon les claviers) — pas avec la quote simple !
  • Déclarer = créer la variable ; initialiser = lui donner sa première valeur. const nom = "Baba" fait les deux.

JS · Fiche Originale

Fiche 44 — Template literals
💡 En clair

Un template literal est une chaîne entre backticks `` dans laquelle tu peux insérer des variables avec ${...} — et écrire sur plusieurs lignes.

JS
const nom = "Baba";
const ville = "Dakar";

const message = `Bonjour ${nom},
tu es à ${ville} !`;

console.log(message);
Console
Bonjour Baba,
tu es à Dakar !
✏️ Ligne par ligne
` ... `backticks OBLIGATOIRES pour ${}
${nom}JS remplace par la valeur de la variable
retour la lignedirectement dans le texte, sans \n
🔍 Ce que fait le code

L'ancienne méthode collait les morceaux avec + : "Bonjour " + nom + ", tu es à " + ville. Les backticks font pareil, sans les fragments de guillemets.

⚠️ Pièges fréquents
  • ${...} ne fonctionne QUE dans les backticks : "Bonjour ${nom}" affiche littéralement ${nom}.

JS · Fiche Originale

Fiche 45 — Interpolation ${}
💡 En clair

L'interpolation, c'est le moteur du template literal : ${...} signifie « évalue ce qui est dedans, puis insère le résultat ». Ça accepte variables ET calculs.

JS
const nom = "Baba";
const age = 20;

const message = `Bonjour ${nom},
tu as ${age} ans !`;

console.log(message);
console.log(`Dans 5 ans : ${age + 5}`);
Console
Bonjour Baba,
tu as 20 ans !
Dans 5 ans : 25
✏️ Ligne par ligne
${nom}insère la variable
${age + 5}calcule l'expression PUIS insère le résultat
🔍 Ce que fait le code

Dans ${age + 5}, JS calcule d'abord 20 + 5 = 25, puis écrit 25 dans le texte. Tout ce qui est entre les accolades est du vrai code JS.

⚠️ Pièges fréquents
  • Ne mets pas de guillemets autour de l'expression : ${"age"} insérerait le mot « age », pas la valeur.

JS · Fiche Originale

Fiche 46 — length
💡 En clair

.length donne le nombre de caractères de la chaîne. C'est une propriété : pas de parenthèses, contrairement à une méthode.

JS
const texte = "Bonjour";
console.log(texte.length);   // 7
Console
7
✏️ Ligne par ligne
texte.lengthpropriété : une valeur déjà calculée, pas une action
texte.toUpperCase()méthode : une action, donc des parenthèses
🔍 Ce que fait le code

Les indices des caractères vont de 0 à length − 1 : pour "Bonjour", les indices vont de 0 à 6. Le DERNIER caractère est toujours à texte.length - 1 — le décalage de 1 est le piège n°1 des débutants.

⚠️ Pièges fréquents
  • Les espaces comptent : "Bonjour ".length → 8.
  • .length marche aussi sur les tableaux (nombre d'éléments).

JS · Fiche Originale

Fiche 47 — Modifier la casse
💡 En clair

Deux méthodes qui changent les majuscules/minuscules : toUpperCase() passe TOUT en majuscules, toLowerCase() tout en minuscules.

JS
const texte = "Bonjour";

console.log(texte.toUpperCase());  // "BONJOUR"
console.log(texte.toLowerCase());  // "bonjour"
console.log(texte);                // "Bonjour" (inchangé !)
Console
BONJOUR
bonjour
Bonjour
📖 Mots à connaître
méthodeune action attachée à une valeur, appelée avec le point : valeur.methode().
🔍 Ce que fait le code

La ligne 4 est là pour prouver l'immutabilité : l'original texte n'a PAS changé. Les méthodes renvoient une nouvelle chaîne.

🎯 Bon réflexe

Usage n°1 : comparer sans se soucier de la casse — saisie.toLowerCase() === "oui" accepte « OUI », « Oui », « oui »...

JS · Fiche Originale

Fiche 48 — Rechercher dans une chaîne
💡 En clair

Trois méthodes qui répondent true/false : includes() « contient ? », startsWith() « commence par ? », endsWith() « finit par ? ».

JS
const texte = "JavaScript";

console.log(texte.includes("Java"));     // true
console.log(texte.includes("Python"));   // false
console.log(texte.startsWith("Java"));   // true
console.log(texte.startsWith("Script")); // false
console.log(texte.endsWith("Script"));   // true
console.log(texte.endsWith("Java"));     // false
Console
true
false
true
false
true
false
🔍 Ce que fait le code

Ces méthodes renvoient un boolean : tu peux les utiliser directement dans un if — if (fichier.endsWith(".js")) { ... }.

⚠️ Pièges fréquents
  • Sensible à la casse : "JavaScript".includes("java") → false (J majuscule vs j minuscule).
  • Pour une recherche insensible : texte.toLowerCase().includes(recherche.toLowerCase()).

JS · Fiche Originale

Fiche 49-A — Extraire une partie d'une chaîne (slice)
💡 En clair

slice(début, fin) découpe la chaîne de l'indice début (inclus) à l'indice fin (exclu). Les indices commencent à 0.

JS
const txt = "JavaScript";

console.log(txt.slice(0, 4)); // "Java"
console.log(txt.slice(4, 8)); // "Scri"
console.log(txt.slice(8));    // "pt"
console.log(txt.slice(4));    // "Script"
Console
"Java"
"Scri"
"pt"
"Script"
✏️ Ligne par ligne
slice(0, 4)indices 0, 1, 2, 3 → "Java" (le 4 est exclu)
slice(4, 8)indices 4, 5, 6, 7 → "Scri"
slice(4)sans fin → jusqu'au bout de la chaîne
🔍 Ce que fait le code

Image de la fiche : « Java | Script ». slice(0, 4) coupe avant le trait. Retenir : fin = l'indice où on s'arrête SANS le prendre.

🎯 Bon réflexe

Indices négatifs = compter depuis la fin : txt.slice(-6) → "Script". Très pratique !

JS · Fiche Originale

Fiche 49-B — slice() vs substring()
💡 En clair

substring() découpe aussi, mais avec deux différences : il refuse les indices négatifs, et il échange début/fin si tu les donnes dans le mauvais ordre.

JS
const txt = "JavaScript";

console.log(txt.slice(4, 8));     // "Scri"
console.log(txt.substring(4, 8)); // "Scri" (pareil ici)

console.log(txt.slice(8, 4));     // "" (vide !)
console.log(txt.substring(8, 4)); // "Scri" (échange en 4, 8)
Console
"Scri"
"Scri"
""
"Scri"
✏️ Ligne par ligne
slice avec négatifs✅ accepte : compte depuis la fin
substring avec négatifs❌ les traite comme 0
slice si début > fin→ chaîne vide
substring si début > fin→ échange les deux indices
🎯 Bon réflexe

En pratique : utilise slice par défaut. Retiens juste que substring existe, tu le croiseras dans du code ancien.

JS · Fiche Originale

Fiche 50 — Supprimer les espaces (trim())
💡 En clair

trim() supprime les espaces au début et à la fin de la chaîne — jamais au milieu.

JS
const txt = "   Bonjour   ";

console.log(txt.trim());   // "Bonjour"
console.log(txt);          // "   Bonjour   " (inchangé)
Console
Bonjour
Bonjour
🔍 Ce que fait le code

Comme toutes les méthodes de chaîne, trim() renvoie une NOUVELLE chaîne : l'originale reste intacte. Pour garder le nettoyage : const propre = txt.trim();

⚠️ Pièges fréquents
  • Les espaces au MILIEU restent : "Bon jour".trim() → "Bon jour".
  • Usage n°1 : nettoyer une saisie utilisateur avant de la tester — les espaces accidentels sont invisibles mais cassent les comparaisons.

JS · Fiche Originale

Fiche 51-A — Remplacer du texte (replace)
💡 En clair

replace(ancien, nouveau) remplace la première occurrence seulement — le reste de la chaîne est laissé tel quel.

📖 Mots à connaître
occurrencechaque apparition du texte recherché.
JS
const phrase = "J'aime JavaScript";

console.log(phrase.replace("JavaScript", "Java"));
Console
"J'aime Java"
JS
console.log("2024-09-17".replace("-", "/"));
// "2024/09-17" : seul le PREMIER tiret !
Console
"2024/09-17"
🔍 Ce que fait le code

Le 2e exemple est le piège : replace("-", "/") ne traite que le premier tiret de la date. Pour tous, il faut replaceAll (fiche suivante).

⚠️ Pièges fréquents
  • Comme toujours avec les chaînes : l'originale n'est pas modifiée, une nouvelle chaîne est renvoyée.

JS · Fiche Originale

Fiche 51-B — replace() vs replaceAll()
💡 En clair

La différence tient en un mot : replace() remplace la première occurrence, replaceAll() remplace toutes.

JS
const txt = "Java Java Java";

console.log(txt.replace("Java", "JS"));     // "JS Java Java"
console.log(txt.replaceAll("Java", "JS"));  // "JS JS JS"
Console
"JS Java Java"
"JS JS JS"
✏️ Ligne par ligne
replace()un seul remplacement suffit ? → c'est le bon
replaceAll()on veut tout remplacer ? → c'est le bon
🎯 Bon réflexe

Variante ancienne : replace(/Java/g, "JS") — le /.../g est une expression régulière avec le flag g (global) qui dit « toutes les occurrences ». Tu rencontreras cette syntaxe dans du code existant.

JS · Fiche Originale

Fiche 52-B — SETTER (Modificateur)
💡 En clair

⚠️ Cette fiche vient d'un cours Java (regarde le logo Java en haut à droite) : class Personne, private int, System.out.println n'existent pas en JavaScript. Ne copie pas ce code dans un fichier .js !

💡 En clair

L'idée, elle, est précieuse : au lieu de laisser n'importe qui modifier une donnée (et mettre -5 dans un âge !), on passe par un setter qui contrôle la valeur avant de l'accepter.

📖 Mots à connaître
setterun « modificateur » : une fonction qui reçoit une nouvelle valeur, la vérifie, puis l'applique.
privé (private)une donnée cachée : impossible à modifier directement de l'extérieur.
this.ageen Java, « l'âge de CET objet » — distingue l'attribut du paramètre age.
JS
class Personne {
  #age;                      // champ privé (le # est JS)

  set age(valeur) {
    if (valeur >= 0) {
      this.#age = valeur;    // contrôle : refuser les négatifs
    }
  }

  get age() {
    return this.#age;
  }
}

const p = new Personne();
p.age = 25;            // appelle le SETTER
console.log(p.age);    // appelle le GETTER → 25
Console
25
🔍 Ce que fait le code

En JavaScript moderne, le couple get/set joue exactement le rôle du setter Java de la fiche : p.age = 25 ressemble à une affectation, mais déclenche en réalité ta fonction de contrôle. Le #age rend la vraie donnée privée.

ℹ️ À savoir

Concepts de POO (programmation orientée objet) — tu les approfondiras plus tard dans ton parcours. Retiens juste le principe : modifier en toute sécurité, avec validation.

08
Chapitre 088 fiches

Nombres

NaN, Infinity, Math et conversions

JS · Fiche Originale

Fiche 54 — Entiers et nombres décimaux
💡 En clair

JavaScript a un SEUL type pour tous les nombres : number. Entier (10) ou décimal (3.14), c'est le même type — et le décimal s'écrit toujours avec un point.

JS
const entier = 10;
const negatif = -8;
const decimal = 3.14;
const prix = 19.99;

console.log(typeof entier);   // "number"
console.log(typeof decimal);  // "number"
Console
"number"
"number"
✏️ Ligne par ligne
10, -8, 0entiers
3.14, 19.99décimaux — POINT, jamais de virgule
.5équivaut à 0.5
1e3notation scientifique : 1 × 10³ = 1000
⚠️ Pièges fréquents
  • 3,14 ❌ : la virgule a une autre signification en JS (elle sépare des valeurs).
  • 4 * 2.5 → 10 : les calculs mélangent entiers et décimaux sans problème.

JS · Fiche Originale

Fiche 55 — NaN (Not a Number)
💡 En clair

NaN signifie « Not a Number » : c'est la valeur renvoyée quand un calcul est impossible (diviser du texte, racine d'un négatif...).

JS
console.log("abc" / 2);       // NaN
console.log(0 / 0);           // NaN
console.log(Number("texte")); // NaN
console.log(Math.sqrt(-1));   // NaN
Console
NaN
NaN
NaN
NaN
📖 Mots à connaître
Math.sqrt(x)la racine carrée de x. Celle de −1 n'existe pas parmi les nombres réels → NaN.
Number.isNaN(x)LA façon correcte de tester : Number.isNaN(res) → true si res vaut NaN.
🔍 Ce que fait le code

Paradoxe assumé : typeof NaN vaut "number" — NaN est techniquement une valeur du type number, mais « pas un nombre calculable ».

⚠️ Pièges fréquents
  • NaN est la SEULE valeur inégale à elle-même : NaN === NaN → false !
  • Donc jamais if (res === NaN) — ça ne marchera jamais. Utilise Number.isNaN(res).

JS · Fiche Originale

Fiche 56 — Infinity
💡 En clair

Infinity représente l'infini : plus grand que n'importe quel nombre fini. Contrairement à d'autres langages, 1 / 0 ne plante pas : il renvoie Infinity.

JS
console.log(1 / 0);            // Infinity
console.log(-1 / 0);           // -Infinity
console.log(1e309);            // Infinity (trop grand !)
console.log(Number.MAX_VALUE); // 1.7976931348623157e+308
Console
Infinity
-Infinity
Infinity
1.7976931348623157e+308
📖 Mots à connaître
Number.MAX_VALUEle plus grand nombre représentable en JS : environ 1,8 × 10³⁰⁸. Au-delà → Infinity.
-0le zéro négatif existe : -1 / Infinity → -0. Pour un débutant, considère-le comme 0.
✏️ Ligne par ligne
Infinity + 1→ Infinity (l'infini absorbe tout)
1 / Infinity→ 0
Infinity === Infinity→ true (contrairement à NaN !)
⚠️ Pièges fréquents
  • Tu n'utiliseras presque jamais Infinity toi-même : tu le RENCONTRERAS surtout quand un calcul déraille (division par 0 oubliée).

JS · Fiche Originale

Fiche 57 — Number() : convertir en nombre
💡 En clair

Number(...) convertit une valeur en nombre. Réussite → le nombre ; échec → NaN. Indispensable car les saisies utilisateur arrivent souvent en TEXTE.

JS
console.log(Number("123"));   // 123
console.log(Number("3.14"));  // 3.14
console.log(Number(true));    // 1
console.log(Number(false));   // 0
console.log(Number("abc"));   // NaN
Console
123
3.14
1
0
NaN
✏️ Ligne par ligne
Number("123")texte → number : tu peux enfin calculer dessus
Number(true)true → 1, false → 0
Number("abc")impossible → NaN
🔍 Ce que fait le code

Cas limite à connaître : Number(null) → 0 mais Number(undefined) → NaN. Et les espaces autour sont tolérés : Number(" 42 ") → 42.

⚠️ Pièges fréquents
  • Number("12px") → NaN : TOUTE la chaîne doit être numérique.
  • Avant de calculer sur une saisie : const n = Number(saisie); puis teste avec Number.isNaN(n).

JS · Fiche Originale

Fiche 58 — parseInt(), parseFloat()
💡 En clair

parseInt() lit l'ENTIER au début d'un texte et s'arrête au premier caractère non numérique. parseFloat() lit aussi la partie décimale.

JS
console.log(parseInt("3.14"));    // 3   (s'arrête au point)
console.log(parseFloat("3.14"));  // 3.14
console.log(parseInt("12.8px"));  // 12  ("px" ignoré)
console.log(parseFloat("12.8px"));// 12.8
console.log(parseInt("abc"));     // NaN
Console
3
3.14
12
12.8
NaN
✏️ Ligne par ligne
parseIntpour un entier (un nombre d'articles, un an...)
parseFloatpour un décimal (un prix, une note...)
s'arrête au premier caractère invalidecontrairement à Number(), qui exige que TOUT soit numérique
🔍 Ce que fait le code

C'est LA différence avec Number() : Number("12.8px") → NaN, mais parseFloat("12.8px") → 12.8. parseFloat lit ce qu'il peut, Number est tout ou rien.

⚠️ Pièges fréquents
  • parseInt accepte une base : parseInt("10", 2) → 2 (binaire), parseInt("0x10") → 16 (hexadécimal détecté automatiquement).
  • Si le texte ne COMMENCE pas par un nombre → NaN pour les deux.

JS · Fiche Originale

Fiche 60 — Math
💡 En clair

Math est une boîte à outils intégrée au langage : Math.méthode(...) pour arrondir, prendre le max, générer de l'aléatoire...

JS
console.log(Math.abs(-5));      // 5    valeur absolue
console.log(Math.round(3.6));   // 4    arrondi classique
console.log(Math.floor(3.6));   // 3    arrondi vers le BAS
console.log(Math.ceil(3.2));    // 4    arrondi vers le HAUT
console.log(Math.max(10, 25));  // 25
console.log(Math.min(10, 25));  // 10
console.log(Math.sqrt(16));     // 4    racine carrée
console.log(Math.random());     // 0.4287... entre 0 et 1
Console
5
4
3
4
25
10
4
0.4287...
✏️ Ligne par ligne
Math.round(3.6)→ 4 (à partir de .5 on arrondit vers le haut)
Math.floor(3.6)→ 3 (toujours vers le bas)
Math.ceil(3.2)→ 4 (toujours vers le haut)
Math.PIune constante : 3.14159... SANS parenthèses
JS
// Un entier aléatoire de 0 à 10 :
const hasard = Math.floor(Math.random() * 11);
console.log(hasard);
Console
7
🔍 Ce que fait le code

Le détail de l'astuce : Math.random() donne un nombre entre 0 inclus et 1 exclu ; × 11 l'étend à [0, 11[ ; Math.floor écrase les décimaux → entiers de 0 à 10.

⚠️ Pièges fréquents
  • N'oublie jamais le × 11 (et pas × 10) si tu veux inclure 10 dans les tirages.
  • Math.random() n'est PAS adapté à la cryptographie — c'est un hasard de simulation, pas de sécurité.

JS · Fiche Originale

Fiche 62-V — Problèmes de précision des nombres
💡 En clair

Test célèbre : 0.1 + 0.2 donne 0.30000000000000004. Ce n'est PAS un bug JavaScript : l'ordinateur stocke les décimaux en binaire (norme IEEE 754, utilisée par tous les langages), et certains décimaux n'ont pas de représentation exacte en binaire.

JS
console.log(0.1 + 0.2);              // 0.30000000000000004
console.log(0.1 + 0.2 === 0.3);      // false !
console.log(1 - 0.9);                // 0.09999999999999998

// La correction : arrondir
const somme = Number((0.1 + 0.2).toFixed(1));
console.log(somme);                  // 0.3
Console
0.30000000000000004
false
0.09999999999999998
0.3
✏️ Ligne par ligne
(0.1 + 0.2).toFixed(1)arrondit à 1 décimale → "0.3" (du TEXTE)
Number(...)reconvertit le texte en nombre → 0.3
🎯 Bon réflexe

Pour l'argent, la vraie méthode pro : compter en CENTIMES (entiers). 0,10 € + 0,20 € devient 10 + 20 = 30 centimes — plus aucune perte de précision.

⚠️ Pièges fréquents
  • Ne compare jamais deux décimaux calculés avec === : compare leurs versions arrondies, ou travaille en entiers.
  • Tous les langages à nombres binaires ont ce comportement : Python, Java, C... Ce n'est pas toi qui te trompes.

JS · Fiche Originale

Fiche 63-2 — BigInt
?? À retenir

BigInt complète number pour les entiers dépassant sa précision fiable. Le suffixe n fait partie de la valeur.

09
Chapitre 0912 fiches

Tableaux

Lire, modifier, parcourir et transformer des collections

JS · Fiche Originale

Fiche 64 — Tableau
💡 En clair

Un tableau est une liste ordonnée de valeurs, regroupée dans une seule variable. Chaque valeur occupe une case numérotée appelée indice, qui commence à 0. Sans tableau, il faudrait une variable par valeur ; avec un tableau, tout est rangé dans une seule structure.

Sans tableau, on écrirait let fruit1 = "pomme", let fruit2 = "banane"... Avec un tableau, tout tient dans une seule variable :

JS
let fruits = ["pomme", "banane", "mangue"];
let nombres = [10, 20, 30];
let mixte = ["Awa", 25, true, null];
let vide = [];

console.log(fruits);
console.log(fruits.length);
Console
[ 'pomme', 'banane', 'mangue' ]
3
✏️ Ligne par ligne
let fruits = ["pomme", "banane", "mangue"];un tableau de 3 chaînes, indices 0, 1, 2.
let mixte = ["Awa", 25, true, null];un tableau peut mélanger tous les types.
let vide = [];un tableau vide, longueur 0.
fruits.lengthrenvoie la taille du tableau (3 ici).
📖 Mots à connaître
indicela position d'une valeur dans le tableau. Le premier est à l'indice 0, le deuxième à 1, etc.
lengthpropriété qui donne le nombre d'éléments du tableau.
tableau littéralla syntaxe [ ] pour créer un tableau — la plus courante.
⚠️ Pièges fréquents
  • Les indices commencent à 0, pas à 1 : fruits[1] renvoie "banane", pas "pomme".
  • fruits[3] ne provoque pas d'erreur mais renvoie undefined si l'indice n'existe pas.
💡 Astuce

Rappel : un tableau est en réalité un objet spécial avec des méthodes comme .push(), .map(), .filter() — voir le chapitre 09 pour les parcourir et les transformer.

JS · Fiche Originale

Fiche 65 — Creer un tableau
💡 En clair

On crée un tableau avec les crochets [ ] : c'est la méthode littérale, recommandée en JavaScript moderne. Le constructeur new Array() existe mais reste rare, moins lisible et comporte un piège important.

Méthode 1 — Littérale (recommandée) :

JS
let fruits = ["pomme", "banane", "mangue"];
let nombres = [1, 2, 3, 4, 5];
let vide = [];

Méthode 2 — Avec le constructeur (à éviter) :

JS
let fruits = new Array("pomme", "banane", "mangue");
let vide = new Array();

// ⚠️ Piège :
let cinq = new Array(5); // [ <5 empty items> ], pas [5] !
console.log(cinq.length); // 5
Console
5

Exemple — Tableau imbriqué (matrice) :

JS
let grille = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
];

console.log(grille[1][2]); // 6
Console
6
✏️ Ligne par ligne
new Array(5)crée un tableau vide de longueur 5 — pas un tableau contenant 5 !
grille[1][2]accède à la 3ᵉ valeur de la 2ᵉ ligne (indices 0-based).
let vide = [];crée un tableau vide — la forme recommandée.
⚠️ Pièges fréquents
  • new Array(5) crée un tableau de longueur 5 vide, pas un tableau contenant le nombre 5. Préfère toujours [5].
  • Mélanger les types dans un tableau est possible mais rend le code moins prévisible — à réserver aux cas légitimes.
💡 Astuce

Toujours utiliser les crochets [ ] : c'est court, clair, sans piège, et c'est la convention moderne.

JS · Fiche Originale

Fiche 66 — Indices
💡 En clair

Un indice est la position d'un élément dans le tableau. Il commence à 0 : fruits[0] est le premier, fruits[1] le deuxième. Pour un tableau de longueur n, les indices valides vont de 0 à n - 1.

JS
let fruits = ["pomme", "banane", "mangue"];

console.log(fruits[0]);  // "pomme"
console.log(fruits[1]);  // "banane"
console.log(fruits[2]);  // "mangue"
console.log(fruits[3]);  // undefined

let dernier = fruits[fruits.length - 1];
console.log(dernier);   // "mangue"
Console
pomme
banane
mangue
undefined
mangue
✏️ Ligne par ligne
fruits[0]premier élément — l'indice commence à 0.
fruits[3]indice invalide → pas d'erreur, mais undefined.
fruits[fruits.length - 1]astuce pour lire le dernier élément.
📖 Mots à connaître
indicela position d'un élément, à partir de 0.
lengthle nombre d'éléments ; length - 1 donne l'indice du dernier.
undefinedce que retourne un indice inexistant — jamais d'erreur.
⚠️ Pièges fréquents
  • Un indice invalide ne déclenche pas d'erreur : il retourne undefined. À surveiller dans les boucles pour éviter des bugs silencieux.
  • Le premier élément est à l'indice 0, pas 1. Conventions informatiques classiques.

JS · Fiche Originale

Fiche 68 — Modifier un élément
💡 En clair

On modifie un élément en lui assignant une nouvelle valeur via son indice : tableau[indice] = nouvelleValeur. La longueur du tableau ne change pas — sauf si l'on écrit au-delà de la fin. La propriété length est elle-même modifiable.

JS
let fruits = ["pomme", "banane", "mangue"];
fruits[1] = "fraise";
console.log(fruits);

let notes = [12, 15, 18];
notes[0] = 14;
console.log(notes);

console.log(fruits.length);
Console
[ 'pomme', 'fraise', 'mangue' ]
[ 14, 15, 18 ]
3
✏️ Ligne par ligne
fruits[1] = "fraise";remplace la valeur à l'indice 1.
notes[0] = 14;met à jour la première note.
fruits.lengthtoujours 3 : la modification ne change pas la longueur.

Réduire length coupe le tableau :

JS
let fruits = ["pomme", "banane", "mangue"];
fruits.length = 2;
console.log(fruits);  // ["pomme", "banane"]
Console
[ 'pomme', 'banane' ]
⚠️ Pièges fréquents
  • Écrire à un indice au-delà de la longueur remplit les cases manquantes avec undefined : fruits[5] = "kiwi" crée un tableau « troué » — légal mais rarement voulu.
  • length est modifiable : fruits.length = 2 coupe le tableau. À utiliser avec prudence.
💡 Astuce

Pour lire le dernier élément sans calcul : fruits.at(-1) (méthode moderne). Sinon : fruits[fruits.length - 1].

JS · Fiche Originale

Fiche 71 — pop(), shift() et unshift()
💡 En clair

Ces quatre méthodes ajoutent ou retirent des éléments aux extrémités du tableau. push() et unshift() ajoutent, pop() et shift() retirent. Toutes modifient le tableau original.

📖 Mots à connaître
push()ajoute à la FIN. Retourne la nouvelle longueur.
pop()retire le DERNIER. Retourne l'élément retiré.
unshift()ajoute au DÉBUT. Retourne la nouvelle longueur.
shift()retire le PREMIER. Retourne l'élément retiré.
JS
let fruits = ["pomme", "banane"];

fruits.push("mangue");
console.log(fruits);

fruits.unshift("kiwi", "fraise");
console.log(fruits);

let dernier = fruits.pop();
console.log(dernier, fruits);

let premier = fruits.shift();
console.log(premier, fruits);
Console
[ 'pomme', 'banane', 'mangue' ]
[ 'kiwi', 'fraise', 'pomme', 'banane', 'mangue' ]
mangue [ 'kiwi', 'fraise', 'pomme', 'banane' ]
kiwi [ 'fraise', 'pomme', 'banane' ]
✏️ Ligne par ligne
fruits.push("mangue");ajoute à la fin — nouvelle longueur 3.
fruits.unshift("kiwi", "fraise");ajoute au début — décale tout vers la droite.
fruits.pop();retire le dernier ("mangue") et le retourne.
fruits.shift();retire le premier ("kiwi") et le retourne.
⚠️ Pièges fréquents
  • pop() et shift() sur un tableau vide retournent undefined, sans erreur.
  • unshift() et shift() décalent tous les éléments : plus lents que push()/pop() sur les grands tableaux.
💡 Astuce

Pour une file d'attente (premier arrivé, premier servi) : combine push() pour ajouter et shift() pour retirer. Pour une pile : push() + pop().

JS · Fiche Originale

Fiche 74a — slice() et splice()
💡 En clair

slice() et splice() ont des noms proches mais des effets opposés : slice() extrait une copie sans toucher à l'original, tandis que splice() modifie le tableau pour supprimer, insérer ou remplacer.

📖 Mots à connaître
slice(début, fin)extrait de début (inclus) à fin (exclu). Retourne un nouveau tableau.
splice(début, nb, ...ajouts)supprime nb éléments à partir de début, puis insère les ajouts. Modifie l'original.

slice() — extraire sans modifier :

JS
let fruits = ["pomme", "banane", "mangue", "kiwi", "fraise"];

let extrait = fruits.slice(1, 3);
console.log(extrait);
console.log(fruits);  // intact

console.log(fruits.slice(-2));  // deux derniers
Console
[ 'banane', 'mangue' ]
[ 'pomme', 'banane', 'mangue', 'kiwi', 'fraise' ]
[ 'kiwi', 'fraise' ]

splice() — supprimer, insérer, remplacer :

JS
let fruits = ["pomme", "banane", "mangue", "kiwi"];

fruits.splice(1, 2);  // supprime 2 à partir de 1
console.log(fruits);

fruits.splice(1, 0, "banane", "mangue");  // insère
console.log(fruits);

fruits.splice(1, 1, "fraise");  // remplace
console.log(fruits);
Console
[ 'pomme', 'kiwi' ]
[ 'pomme', 'banane', 'mangue', 'kiwi' ]
[ 'pomme', 'fraise', 'mangue', 'kiwi' ]
✏️ Ligne par ligne
fruits.slice(1, 3);extrait les indices 1 et 2 (fin 3 exclue). Original intact.
fruits.splice(1, 2);supprime 2 éléments à partir de l'indice 1. Original modifié.
fruits.splice(1, 0, "banane", "mangue");insère à l'indice 1 sans rien supprimer (nb = 0).
fruits.splice(1, 1, "fraise");remplace 1 élément à l'indice 1.
💡 Astuce

Moyen mnémotechnique : slice = tranche (on coupe sans abîmer), splice = épissure (on modifie la structure). Un seul « p » change tout.

JS · Fiche Originale

Fiche 78 — find() et findIndex()
💡 En clair

Ces méthodes recherchent des éléments : includes() et indexOf() testent une valeur exacte ; find() et findIndex() testent une condition. Toutes parcourent le tableau jusqu'au premier résultat, puis s'arrêtent.

📖 Mots à connaître
includes(valeur)retourne true/false. Détecte NaN.
indexOf(valeur)retourne l'indice ou -1. Ne détecte pas NaN.
find(callback)retourne le premier élément qui satisfait la condition, sinon undefined.
findIndex(callback)retourne l'indice du premier élément qui satisfait la condition, sinon -1.
JS
let fruits = ["pomme", "banane", "mangue"];

console.log(fruits.includes("banane"));  // true
console.log(fruits.indexOf("kiwi"));      // -1

let nombres = [4, 9, 15, 22, 7];
let grand = nombres.find((n) => n > 10);
let index = nombres.findIndex((n) => n > 10);
console.log(grand, index);
Console
true
-1
15 2
✏️ Ligne par ligne
includes("banane")présence d'une valeur exacte → true.
indexOf("kiwi")position d'une valeur absente → -1.
find((n) => n > 10)condition : renvoie l'élément 15.
findIndex((n) => n > 10)même condition : renvoie l'indice 2.

Trouver un objet dans une liste :

JS
let utilisateurs = [
  { nom: "Awa", age: 25 },
  { nom: "Moussa", age: 30 },
  { nom: "Fatou", age: 25 }
];

let u = utilisateurs.find((u) => u.nom === "Moussa");
console.log(u);
Console
{ nom: 'Moussa', age: 30 }
⚠️ Pièges fréquents
  • includes() utilise la comparaison stricte === : [1, 2, 3].includes("2") retourne false.
  • indexOf() ne détecte pas NaN : [NaN].indexOf(NaN) retourne -1. Préférer includes() dans ce cas.
💡 Astuce

Pour modifier ou supprimer un élément après l'avoir trouvé : let i = arr.findIndex(...); if (i !== -1) arr.splice(i, 1);.

JS · Fiche Originale

Fiche 80 — filter() et map()
💡 En clair

filter() et map() créent toutes deux un nouveau tableau, sans modifier l'original. filter() garde ou rejette (longueur variable), map() transforme (longueur identique).

📖 Mots à connaître
filter(callback)retourne un tableau avec uniquement les éléments qui passent le test.
map(callback)retourne un tableau de même longueur où chaque élément est transformé.
JS
let nombres = [4, 9, 15, 22, 7];

let grands = nombres.filter((n) => n > 10);
console.log(grands, nombres);

let doubles = nombres.map((n) => n * 2);
console.log(doubles);
Console
[ 15, 22 ] [ 4, 9, 15, 22, 7 ]
[ 8, 18, 30, 44, 14 ]

Exemple concret — filtrer et extraire des noms :

JS
let utilisateurs = [
  { nom: "Awa", age: 25 },
  { nom: "Moussa", age: 30 },
  { nom: "Fatou", age: 17 }
];

let noms = utilisateurs.map((u) => u.nom);
let majeurs = utilisateurs.filter((u) => u.age >= 18);

console.log(noms);
console.log(majeurs.length);
Console
[ 'Awa', 'Moussa', 'Fatou' ]
2
✏️ Ligne par ligne
filter((n) => n > 10)garde 15 et 22 — tableau plus court.
map((n) => n * 2)transforme chaque élément — même longueur.
utilisateurs.map((u) => u.nom)extrait la propriété nom de chaque objet.
utilisateurs.filter((u) => u.age >= 18)ne garde que les majeurs.
💡 Astuce

On peut chaîner les deux : users.filter(u => u.actif).map(u => u.nom) renvoie les noms des utilisateurs actifs.

JS · Fiche Originale

Fiche 82 — forEach(), some() et every()
💡 En clair

forEach() exécute une action pour chaque élément (sans rien retourner), some() vérifie si au moins un élément passe un test, every() exige que tous passent.

📖 Mots à connaître
forEach(callback)parcourt et agit. Retourne undefined.
some(callback)retourne true dès qu'un élément passe le test.
every(callback)retourne false dès qu'un élément échoue.
JS
let fruits = ["pomme", "banane", "mangue"];

fruits.forEach((fruit, i) => {
  console.log(i, fruit);
});

let ages = [12, 15, 17, 18];
console.log(ages.some((a) => a >= 18));
console.log(ages.every((a) => a >= 18));
Console
0 pomme
1 banane
2 mangue
true
false
✏️ Ligne par ligne
forEach((fruit, i) => ...)boucle sur chaque élément avec son indice.
some((a) => a >= 18)au moins un majeur ? → true (18).
every((a) => a >= 18)tous majeurs ? → false (12, 15, 17).
⚠️ Pièges fréquents
  • forEach() ne retourne rien : let r = arr.forEach(...) donne undefined. Pour transformer, utiliser map().
  • some() et every() s'arrêtent dès qu'ils ont la réponse : pas besoin de parcourir tout le tableau.
💡 Astuce

Différence avec includes() : ce dernier teste une valeur exacte, some() teste une condition. Pour « le tableau contient-il un nombre > 100 ? », c'est some() qu'il faut.

JS · Fiche Originale

Fiche 85a — reduce()
💡 En clair

reduce() réduit un tableau à une seule valeur en transportant un accumulateur d'élément en élément. Imagine une tirelire : on part d'un montant initial, puis on ajoute chaque pièce une par une. C'est l'outil le plus puissant des méthodes de tableau.

Anatomie :

JS
let somme = [1, 2, 3, 4].reduce((acc, n) => acc + n, 0);
console.log(somme);
Console
10
✏️ Ligne par ligne
accl'accumulateur : valeur transportée d'étape en étape.
nl'élément courant du tableau.
0la valeur initiale — souvent 0 pour une somme, 1 pour un produit, [] pour un tableau.
return acc + n;combine l'accumulateur avec l'élément courant.

Au-delà de la somme — compter les occurrences :

JS
let fruits = ["pomme", "banane", "pomme", "mangue", "pomme"];

let compteur = fruits.reduce((acc, fruit) => {
  acc[fruit] = (acc[fruit] || 0) + 1;
  return acc;
}, {});

console.log(compteur);
Console
{ pomme: 3, banane: 1, mangue: 1 }

Aplatir un tableau de tableaux :

JS
let groupes = [[1, 2], [3, 4], [5]];
let plat = groupes.reduce((acc, g) => acc.concat(g), []);
console.log(plat);
Console
[ 1, 2, 3, 4, 5 ]
⚠️ Pièges fréquents
  • Oublier la valeur initiale est un piège fréquent : sans second argument, reduce() utilise le premier élément du tableau — ce qui casse sur un tableau vide.
  • Sur un tableau vide sans valeur initiale : TypeError: Reduce of empty array with no initial value.
💡 Astuce

Choix de la valeur initiale : 0 pour somme, 1 pour produit, [] pour aplatir, {} pour regrouper, premier élément pour un maximum.

JS · Fiche Originale

Fiche 86b — Trier des nombres correctement
💡 En clair

sort() trie le tableau en place (il modifie l'original). Par défaut, il convertit tout en chaînes et trie alphabétiquement — d'où des résultats surprenants pour les nombres. Pour trier correctement, toujours fournir une fonction de comparaison.

JS
let fruits = ["mangue", "banane", "pomme"];
fruits.sort();
console.log(fruits);

let nombres = [10, 2, 30, 4];
nombres.sort();
console.log(nombres);  // piège !

nombres.sort((a, b) => a - b);
console.log(nombres);  // OK
Console
[ 'banane', 'mangue', 'pomme' ]
[ 10, 2, 30, 4 ]
[ 2, 4, 10, 30 ]
✏️ Ligne par ligne
fruits.sort();tri alphabétique — correct pour des chaînes.
nombres.sort();convertit en chaînes : "10" < "2" — faux pour des nombres.
nombres.sort((a, b) => a - b);si a - b négatif, a vient avant b. Tri croissant.

Tri décroissant, tri d'objets, et reverse() :

JS
nombres.sort((a, b) => b - a);
console.log(nombres);  // [30, 10, 4, 2]

let users = [
  { nom: "Awa", age: 25 },
  { nom: "Moussa", age: 30 },
  { nom: "Fatou", age: 20 }
];
users.sort((a, b) => a.age - b.age);
console.log(users[0].nom);  // "Fatou"

let inverse = [...nombres].reverse();
console.log(inverse);
Console
[ 30, 10, 4, 2 ]
Fatou
[ 2, 4, 10, 30 ]
⚠️ Pièges fréquents
  • sort() et reverse() modifient l'original. Pour préserver : let trié = [...arr].sort(...).
  • Tri de chaînes avec accents : (a, b) => a.localeCompare(b) — gère correctement les majuscules et les caractères accentués.
💡 Astuce

Astuce : (a, b) => a - b trie par ordre croissant (petit → grand), (a, b) => b - a par ordre décroissant. Pour combiner tri + inversion sans risque, copier d'abord avec [...arr].

JS · Fiche Originale

Fiche 88 — Destructuration de tableau
💡 En clair

La déstructuration extrait des valeurs d'un tableau dans des variables distinctes en une seule ligne : let [a, b, c] = tableau;. Le spread ... étale les éléments pour les copier, les fusionner ou les passer en arguments. Les deux vont de pair avec la copie de tableau.

Déstructuration — extraire dans des variables :

JS
let fruits = ["pomme", "banane", "mangue"];

let [premier, deuxieme, troisieme] = fruits;
console.log(premier, deuxieme, troisieme);

let [a, , c] = fruits;  // ignorer le 2e
console.log(a, c);

let [x = 1, y = 2] = [10];  // valeurs par défaut
console.log(x, y);
Console
pomme banane mangue
pomme mangue
10 2
✏️ Ligne par ligne
let [premier, deuxieme, troisieme] = fruits;extrait dans l'ordre : trois variables pour trois éléments.
let [a, , c] = fruits;la virgule vide ignore le 2e élément.
let [x = 1, y = 2] = [10];valeurs par défaut si l'élément est absent.

Échanger deux variables sans variable temporaire :

JS
let x = 1, y = 2;
[x, y] = [y, x];
console.log(x, y);
Console
2 1

Spread ... — copier, fusionner, passer en arguments :

JS
let original = [1, 2, 3];
let copie = [...original];  // copie indépendante

let a = [1, 2], b = [3, 4];
let fusion = [...a, ...b];  // [1, 2, 3, 4]

let complet = [1, ...a, 5];  // [1, 1, 2, 5]

console.log(Math.max(...[5, 2, 8, 1]));  // 8

let lettres = [..."abc"];
console.log(lettres);
Console
8
[ 'a', 'b', 'c' ]

Rest operator — récupérer les éléments restants :

JS
let fruits = ["pomme", "banane", "mangue"];
let [premier, ...reste] = fruits;
console.log(premier, reste);
Console
pomme [ 'banane', 'mangue' ]
⚠️ Pièges fréquents
  • let copie = original ne copie PAS le tableau : les deux variables pointent vers le même. Utiliser [...original] ou original.slice().
  • Pour les tableaux imbriqués, [...] ne copie que le premier niveau (shallow copy). Utiliser structuredClone(original) pour une copie profonde.
💡 Astuce

Le spread ... et le rest ...reste utilisent la même syntaxe, mais dans des contextes opposés : spread « ouvre » un tableau, rest « ramasse » plusieurs valeurs dans un tableau.

10
Chapitre 107 fiches

Fonctions

Réutiliser du code et transmettre des comportements

JS · Fiche Originale

Fiche 91 — Pourquoi utiliser une fonction ?
💡 En clair

Une fonction est un bloc de code nommé, réutilisable. Elle regroupe une action (calcul, affichage, transformation) qu'on peut exécuter autant de fois qu'on veut, sans réécrire le code. C'est le moyen d'éviter la répétition et de structurer un programme.

Sans fonction — on répète le même calcul :

JS
let aire1 = 5 * 4;
let aire2 = 7 * 3;
let aire3 = 10 * 2;
// ... lourd et source d'erreurs

Avec une fonction — on factorise :

JS
function aire(longueur, largeur) {
  return longueur * largeur;
}

console.log(aire(5, 4));
console.log(aire(7, 3));
console.log(aire(10, 2));
Console
20
21
20
✏️ Ligne par ligne
function aire(longueur, largeur) { ... }déclare une fonction nommée aire avec 2 paramètres.
return longueur * largeur;renvoie le résultat à l'appelant.
aire(5, 4)appelle la fonction avec les arguments 5 et 4.
📖 Mots à connaître
fonctionun bloc de code nommé, réutilisable, qui effectue une action précise.
paramètreune variable déclarée entre les parenthèses — l'entrée de la fonction.
returnle mot-clé qui renvoie une valeur à celui qui a appelé la fonction.
⚠️ Pièges fréquents
  • Définir une fonction ne l'exécute pas : il faut l'appeler avec aire(5, 4) pour qu'elle s'exécute.
  • Oublier return renvoie undefined — la fonction s'exécute mais ne produit rien.
💡 Astuce

Règle d'or : si tu écris le même code 2-3 fois, place-le dans une fonction. C'est le principe DRY (Don't Repeat Yourself).

JS · Fiche Originale

Fiche 93 — Paramètres et arguments
💡 En clair

Les paramètres sont les variables déclarées entre les parenthèses lors de la définition d'une fonction. Les arguments sont les valeurs concrètes qu'on passe lors de l'appel. Cette distinction permet à une même fonction de travailler avec des données différentes à chaque appel.

JS
function saluer(prenom, langue) {
  if (langue === "fr") return "Bonjour " + prenom;
  if (langue === "en") return "Hello " + prenom;
  return "Salut " + prenom;
}

console.log(saluer("Awa", "fr"));
console.log(saluer("John", "en"));
Console
Bonjour Awa
Hello John
✏️ Ligne par ligne
prenom, langueles 2 paramètres — des variables "vides" en attente de valeur.
saluer("Awa", "fr")appel avec les arguments "Awa" et "fr".
return "Bonjour " + prenom;utilise le paramètre comme une variable locale.

Valeurs par défaut (ES6) : si un argument manque, on peut prévoir une valeur :

JS
function saluer(prenom = "visiteur") {
  return "Bonjour " + prenom;
}

console.log(saluer("Awa"));  // "Bonjour Awa"
console.log(saluer());      // "Bonjour visiteur"
Console
Bonjour Awa
Bonjour visiteur
📖 Mots à connaître
paramètrela variable déclarée entre les parenthèses (côté définition).
argumentla valeur réelle passée lors de l'appel (côté utilisation).
valeur par défautvaleur utilisée quand l'argument n'est pas fourni.
⚠️ Pièges fréquents
  • Trop d'arguments passés → les extras sont ignorés silencieusement (pas d'erreur).
  • Pas assez d'arguments → les paramètres manquants valent undefined, ce qui peut casser le calcul.
💡 Astuce

Rappel : voir la fiche 96 sur les paramètres par défaut pour rendre une fonction robuste face aux arguments manquants.

JS · Fiche Originale

Fiche 98a — Fonction fâch??e
💡 En clair

Une arrow function (fonction fléchée) est une syntaxe courte introduite en ES6 pour déclarer une fonction. Elle est idéale pour les petites fonctions, surtout les callbacks. Syntaxe : (params) => expression.

Comparaison des deux syntaxes :

JS
// Fonction classique
function additionner(a, b) {
  return a + b;
}

// Arrow function équivalente
const additionner = (a, b) => a + b;

console.log(additionner(2, 3));
Console
5
✏️ Ligne par ligne
(a, b) => a + bsyntaxe courte : return implicite quand le corps est une expression.
const additionner = ...on stocke la fonction dans une variable (fonction expression).
additionner(2, 3)même appel qu'une fonction classique.

Variante avec corps explicite (multi-lignes) :

JS
const saluer = (prenom) => {
  const message = "Bonjour " + prenom;
  return message;
};

// Avec un seul paramètre, on peut omettre les parenthèses
const carre = x => x * x;
console.log(carre(5));
Console
25
📖 Mots à connaître
arrow functionfonction déclarée avec =>, plus courte qu'une fonction classique.
return implicitequand le corps est une expression sans accolades, elle est renvoyée automatiquement.
callbackfonction passée en argument à une autre fonction — cas idéal des arrow functions.
⚠️ Pièges fréquents
  • Les arrow functions ne possèdent pas leur propre this — voir la fiche 115D. À éviter pour les méthodes d'objet qui utilisent this.
  • Si le corps contient plusieurs instructions, il faut obligatoirement les accolades { } et un return explicite.
💡 Astuce

Rappel : voir la fiche 99 pour comparer arrow function vs fonction classique, et la fiche 101 sur les callbacks — terrain de jeu idéal des arrows.

JS · Fiche Originale

Fiche 100 — Fonction comme valeur
💡 En clair

En JavaScript, une fonction est une valeur comme une autre. On peut la stocker dans une variable, la passer en argument à une autre fonction, ou la renvoyer. C'est ce qu'on appelle les fonctions first-class — le pilier de la programmation fonctionnelle en JS.

1) Stocker une fonction dans une variable :

JS
const direBonjour = function () {
  return "Bonjour !";
};

console.log(direBonjour());  // on appelle via la variable
Console
Bonjour !

2) Passer une fonction en argument (callback) :

JS
function appliquer(f, valeur) {
  return f(valeur);
}

const doubler = x => x * 2;
const carre = x => x * x;

console.log(appliquer(doubler, 5));  // 10
console.log(appliquer(carre, 5));    // 25
Console
10
25
✏️ Ligne par ligne
appliquer(doubler, 5)on passe la fonction doubler comme argument — pas de parenthèses !
return f(valeur);à l'intérieur, on exécute f en l'appelant avec valeur.
appliquer(carre, 5)même fonction, autre callback → résultat différent.

3) Stocker des fonctions dans un tableau :

JS
const operations = [
  (a, b) => a + b,
  (a, b) => a - b,
  (a, b) => a * b
];

console.log(operations[0](10, 3));  // 13
console.log(operations[2](10, 3));  // 30
Console
13
30
📖 Mots à connaître
first-classune fonction est une valeur manipulable comme un nombre ou une chaîne.
callbackune fonction passée en argument, exécutée plus tard par une autre fonction.
higher-orderune fonction qui reçoit ou renvoie une autre fonction.
⚠️ Pièges fréquents
  • Passer direBonjour() au lieu de direBonjour exécute la fonction immédiatement — c'est l'erreur la plus fréquente. Sans parenthèses, on passe la fonction elle-même.
  • Une fonction stockée dans une variable const ne peut pas être réaffectée — mais elle peut toujours être appelée.
💡 Astuce

Voir la fiche 101 sur les callbacks et la fiche 103 sur les fonctions qui retournent des fonctions.

JS · Fiche Originale

Fiche 101 — Callback
💡 En clair

Un callback est une fonction passée en argument à une autre fonction, qui se charge de l'appeler au bon moment. C'est le pilier de l'asynchrone et des méthodes de tableau (.map(), .filter(), .forEach()...).

Exemple simple — un callback synchrone :

JS
function saluer(nom, callback) {
  const message = "Bonjour " + nom;
  callback(message);
}

saluer("Awa", (msg) => {
  console.log("Callback reçoit :", msg);
});
Console
Callback reçoit : Bonjour Awa
✏️ Ligne par ligne
function saluer(nom, callback)saluer accepte un nom ET une fonction callback.
callback(message);à l'intérieur, on appelle le callback en lui passant le message.
saluer("Awa", (msg) => { ... })à l'appel, on fournit la fonction à exécuter.

Exemple réel — setTimeout et .forEach utilisent des callbacks :

JS
const fruits = ["pomme", "banane", "mangue"];

// forEach appelle le callback pour chaque élément
fruits.forEach((fruit, i) => {
  console.log(i + " : " + fruit);
});

// setTimeout appelle le callback après un délai
setTimeout(() => console.log("3 secondes écoulées"), 3000);
Console
0 : pomme
1 : banane
2 : mangue
3 secondes écoulées
📖 Mots à connaître
callbackfonction passée en argument, exécutée "plus tard" par la fonction qui la reçoit.
synchronecallback appelé immédiatement (ex. .forEach).
asynchronecallback appelé plus tard (ex. setTimeout, fetch).
⚠️ Pièges fréquents
  • Le callback hell apparaît quand on imbrique trop de callbacks asynchrones — voir la fiche 182. Les Promesses (chapitre 18) y remédient.
  • Le callback ne s'exécute que quand la fonction qui le reçoit décide de l'appeler — ne pas confondre avec une fonction appelée immédiatement.
💡 Astuce

Rappel : voir le chapitre 09 sur les méthodes de tableau (map, filter, forEach) qui utilisent toutes des callbacks, et le chapitre 15 sur l'asynchrone.

JS · Fiche Originale

Fiche 102 — Fonction qui retourne
💡 En clair

Une fonction peut retourner une valeur grâce au mot-clé return. La valeur renvoyée peut ensuite être stockée, affichée ou réutilisée. Sans return, la fonction s'exécute mais renvoie undefined — son résultat est perdu.

JS
function additionner(a, b) {
  return a + b;
}

const resultat = additionner(3, 4);
console.log(resultat);
console.log(additionner(10, 20) + 5);
Console
7
35
✏️ Ligne par ligne
return a + b;renvoie la somme — l'appelant la reçoit.
const resultat = additionner(3, 4);on capture la valeur de retour dans une variable.
additionner(10, 20) + 5on peut utiliser directement le retour dans une expression.

Le return arrête immédiatement la fonction :

JS
function verifierAge(age) {
  if (age < 0) return "Âge invalide";
  if (age >= 18) return "Majeur";
  return "Mineur";
}

console.log(verifierAge(-5));
console.log(verifierAge(25));
console.log(verifierAge(12));
Console
Âge invalide
Majeur
Mineur
📖 Mots à connaître
returnmot-clé qui renvoie une valeur et stoppe l'exécution de la fonction.
undefinedla valeur renvoyée par défaut si aucun return n'est atteint.
early returntechnique qui consiste à returner tôt pour éviter les imbrications profondes.
⚠️ Pièges fréquents
  • return arrête la fonction : tout code écrit après un return n'est jamais exécuté.
  • Oublier return renvoie undefined — l'erreur la plus courante chez les débutants.
💡 Astuce

Rappel : voir la fiche 91 sur pourquoi une fonction et la fiche 95 sur return dans les fonctions imbriquées.

JS · Fiche Originale

Fiche 104a — Scope
💡 En clair

Le scope (portée) définit où une variable est accessible dans le code. Une variable déclarée dans une fonction n'existe que dans cette fonction — c'est le scope local. Une variable déclarée en dehors de toute fonction est globale, accessible partout.

JS
let global = "je suis global";

function test() {
  let local = "je suis local";
  console.log(global);  // OK : global est accessible
  console.log(local);   // OK : local est dans son scope
}

test();
console.log(global);   // OK
console.log(local);    // ❌ ReferenceError : local n'existe pas ici
Console
je suis global
je suis global
je suis local
ReferenceError: local is not defined
✏️ Ligne par ligne
let global = ...déclarée en dehors de toute fonction → scope global.
let local = ...déclarée dans test() → n'existe que pendant l'appel.
console.log(local) hors fonctionéchoue car local a été détruit à la fin de test().

Deux fonctions peuvent avoir des variables locales de même nom sans collision :

JS
function a() {
  let x = 1;
  console.log("a : x =", x);
}

function b() {
  let x = 2;  // x différent de celui de a()
  console.log("b : x =", x);
}

a();
b();
Console
a : x = 1
b : x = 2
📖 Mots à connaître
scopela zone du code où une variable est accessible.
variable globaledéclarée hors fonction, accessible partout — à limiter.
variable localedéclarée dans une fonction, détruite à la fin de l'appel.
⚠️ Pièges fréquents
  • Trop de variables globales rendent un programme difficile à déboguer : une modification accidentelle d'une globale peut casser plusieurs fonctions.
  • Une variable locale est détruite à la fin de la fonction — y accéder depuis l'extérieur provoque une ReferenceError.
💡 Astuce

Rappel : voir la fiche 104B sur le scope de bloc et la fiche 106 sur les closures — un mécanisme qui permet à une fonction de "se souvenir" des variables de son scope englobant.

11
Chapitre 116 fiches

Objets

Propriétès, méthodes et organisation des données

JS · Fiche Originale

Fiche 107 — Objets
💡 En clair

Un objet est une collection de paires clé/valeur. Chaque clé (aussi appelée propriété) a un nom et une valeur associée. Les objets permettent de regrouper des données liées sous un seul nom — comme une fiche signalétique : nom, âge, email, adresse...

Sans objet — la dispersion :

JS
let nom = "Awa";
let age = 25;
let email = "awa@mail.com";
// 3 variables dispersées, difficiles à passer ensemble

Avec un objet — tout est groupé :

JS
let utilisateur = {
  nom: "Awa",
  age: 25,
  email: "awa@mail.com",
  actif: true
};

console.log(utilisateur.nom);
console.log(utilisateur.age);
Console
Awa
25
✏️ Ligne par ligne
{ nom: "Awa", age: 25, ... }un objet littéral : clés et valeurs séparées par deux-points.
utilisateur.nomnotation point : accède à la propriété nom.
utilisateur.agerenvoie la valeur associée à la clé age.

Un objet peut contenir des types variés, y compris des tableaux ou d'autres objets :

JS
let produit = {
  nom: "Clavier",
  prix: 25000,
  tags: ["mécanique", "rétroéclairé"],
  dimensions: { largeur: 44, hauteur: 14 }
};

console.log(produit.tags[0]);
console.log(produit.dimensions.largeur);
Console
mécanique
44
📖 Mots à connaître
propriétéune paire clé/valeur dans un objet (ex. nom: "Awa").
cléle nom de la propriété — une chaîne ou un Symbol.
objet littéralla syntaxe { } pour créer un objet — la plus courante.
⚠️ Pièges fréquents
  • Les clés d'un objet sont uniques : si tu déclares deux fois nom, la dernière écrase la première.
  • Les objets ne sont pas ordonnés comme les tableaux — l'ordre des propriétés n'est pas garanti par la spécification (bien que les moteurs modernes le préservent).
💡 Astuce

Rappel : voir le chapitre 09 sur les tableaux (collections ordonnées) et la fiche 116 sur la destructuration pour extraire des propriétés.

JS · Fiche Originale

Fiche 109 — Propriétès : notation point et crochets
💡 En clair

Il existe deux façons d'accéder à une propriété d'un objet : la notation point (objet.propriete) et la notation crochets (objet["propriete"]). Elles donnent le même résultat quand la clé est un identifiant valide.

JS
let user = {
  nom: "Awa",
  age: 25,
  "ville préférée": "Dakar"
};

// Notation point
console.log(user.nom);

// Notation crochets
console.log(user["age"]);

// Crochets obligatoires pour les clés avec espace
console.log(user["ville préférée"]);
Console
Awa
25
Dakar

Les crochets sont indispensables quand la clé est dynamique :

JS
let user = { nom: "Awa", age: 25, email: "a@b.com" };
let champ = "age";

console.log(user[champ]);    // 25 — la clé est calculée à l'exécution
console.log(user.champ);     // undefined — cherche une clé littérale "champ"
Console
25
undefined
✏️ Ligne par ligne
user.nomnotation point : simple, lisible, réservée aux identifiants valides.
user["age"]notation crochets : accepte n'importe quelle chaîne.
user[champ]quand champ est une variable, on doit utiliser les crochets.
📖 Mots à connaître
notation pointobjet.propriete — simple, pour les clés qui ressemblent à des variables.
notation crochetsobjet["clé"] — accepte les espaces, caractères spéciaux, clés dynamiques.
identifiant validecommence par une lettre/_/$, ne contient que lettres, chiffres, _ et $.
⚠️ Pièges fréquents
  • La notation point échoue sur les clés contenant un espace : user.ville préférée est une erreur de syntaxe. Utiliser user["ville préférée"].
  • Si la clé n'existe pas, on obtient undefined (pas d'erreur) — prêter attention aux fautes de frappe.
💡 Astuce

Règle pratique : utiliser la notation point par défaut (plus lisible). Réserver les crochets aux clés dynamiques ou non valides.

JS · Fiche Originale

Fiche 114 — Méthodes d’objet
💡 En clair

Une méthode est une propriété dont la valeur est une fonction. Elle permet à un objet d'avoir des actions en plus de ses données. On l'appelle via la notation point : objet.methode(). À l'intérieur, this désigne l'objet lui-même.

JS
let user = {
  nom: "Awa",
  age: 25,
  saluer() {
    return "Bonjour, je suis " + this.nom;
  },
  vieillir() {
    this.age++;
  }
};

console.log(user.saluer());
user.vieillir();
console.log(user.age);
Console
Bonjour, je suis Awa
26
✏️ Ligne par ligne
saluer() { ... }syntaxe courte pour une méthode — équivalent à saluer: function() {...}
this.nomthis désigne l'objet courant (user), on accède à sa propriété nom.
this.age++modifie la propriété age de l'objet.

On peut aussi écrire la méthode avec une fonction classique ou une arrow — avec des nuances importantes :

JS
let user = {
  nom: "Awa",
  // Méthode classique — this = user
  saluer() { return "Salut " + this.nom; },
  // Arrow function — ⚠️ this n'est PAS user
  saluerArrow: () => "Salut " + this.nom
};

console.log(user.saluer());
Console
Salut Awa
📖 Mots à connaître
méthodeune fonction stockée comme propriété d'un objet.
thisà l'intérieur d'une méthode classique, désigne l'objet propriétaire.
appel de méthodesyntaxe objet.methode() — les parenthèses déclenchent l'exécution.
⚠️ Pièges fréquents
  • Les arrow functions n'ont pas de this propre — voir la fiche 115D. À éviter pour les méthodes d'objet qui utilisent this.
  • Oublier les parenthèses (user.saluer) renvoie la fonction au lieu de l'exécuter — résultat affiché comme [Function: saluer].
💡 Astuce

Rappel : voir la fiche 115A sur this et la fiche 115D sur le comportement particulier de this avec les arrow functions.

JS · Fiche Originale

Fiche 115a — this
💡 En clair

Le mot-clé this désigne l'objet "courant" à l'intérieur d'une méthode. C'est l'équivalent de "je"/"moi" pour un objet : quand tu appelles user.saluer(), this vaut user. Sa valeur dépend donc de comment la fonction est appelée, pas de comment elle est définie.

JS
let user = {
  nom: "Awa",
  presenter() {
    return "Je suis " + this.nom;
  }
};

let admin = {
  nom: "Admin",
  presenter: user.presenter  // même fonction
};

console.log(user.presenter());
console.log(admin.presenter());
Console
Je suis Awa
Je suis Admin
✏️ Ligne par ligne
this.nom dans presenter()this vaut l'objet qui appelle la méthode.
user.presenter()this = user → "Je suis Awa".
admin.presenter()this = admin → "Je suis Admin", bien que ce soit la même fonction.

Hors d'une méthode, this vaut l'objet global (window ou globalThis) :

JS
function testThis() {
  console.log(this);
}

testThis();  // Window (navigateur) ou globalThis (Node.js)
Console
[object Window]
📖 Mots à connaître
thisdésigne l'objet propriétaire au moment de l'appel — pas une variable fixe.
objet courantl'objet sur lequel la méthode est invoquée (avant le point).
runtime bindingla valeur de this est déterminée à l'exécution, pas à la déclaration.
⚠️ Pièges fréquents
  • this change selon l'appel : user.presenter() ≠ const f = user.presenter; f(); — dans le second cas, this devient l'objet global ou undefined en mode strict.
  • Ne pas confondre avec Python ou Java où this est fixé par la classe. En JS, this est dynamique.
💡 Astuce

Rappel : voir la fiche 115D sur le comportement particulier de this avec les arrow functions, et la fiche 127 sur le constructor qui fixe this pour les instances de classe.

JS · Fiche Originale

Fiche 115d — this et les fonctions fâch??es
💡 En clair

Les arrow functions ne possèdent pas leur propre this : elles empruntent le this du scope englobant (lexical). C'est pratique pour les callbacks, mais problématique pour les méthodes d'objet qui doivent se référer à l'objet courant.

JS
let user = {
  nom: "Awa",
  // Méthode classique — this = user
  classique() { return "Salut " + this.nom; },
  // Arrow function — this = scope englobant (window/global)
  arrow: () => "Salut " + this.nom
};

console.log(user.classique());
console.log(user.arrow());  // this.nom est undefined
Console
Salut Awa
Salut undefined
✏️ Ligne par ligne
classique() { return this.nom; }méthode classique — this est lié à user à l'appel.
arrow: () => this.nomarrow — this est hérité du scope englobant, ici l'objet global.
user.arrow()this.nom cherche nom sur global → undefined.

Mais les arrows sont parfaites pour les callbacks à l'intérieur d'une méthode :

JS
let minuteur = {
  nom: "Awa",
  demarrer() {
    setTimeout(() => {
      console.log(this.nom + " a attendu 1s");
    }, 1000);
  }
};

minuteur.demarrer();  // après 1s : "Awa a attendu 1s"
Console
Awa a attendu 1s
📖 Mots à connaître
this lexicalun arrow function hérite du this du scope englobant (au moment de la définition).
this dynamiqueune fonction classique reçoit this selon l'appel (au moment de l'exécution).
callbackcas idéal pour les arrows — on évite de perdre le this englobant.
⚠️ Pièges fréquents
  • Utiliser une arrow comme méthode d'objet est une source d'erreurs fréquente — this ne pointe pas vers l'objet.
  • Avec setTimeout(function() { ... }) classique, this devient global — d'où l'intérêt des arrows dans ce cas.
💡 Astuce

Règle : arrow = idéal pour les callbacks à l'intérieur d'une méthode. Méthode classique = pour les méthodes d'objet qui utilisent this.

JS · Fiche Originale

Fiche 116 — Destructuration d’objet
💡 En clair

La destructuration d'objet (destructured assignment) permet d'extraire plusieurs propriétés d'un objet en une seule ligne. Au lieu d'écrire const nom = user.nom; const age = user.age;, on écrit const { nom, age } = user; — plus court et plus lisible.

JS
let user = {
  nom: "Awa",
  age: 25,
  email: "awa@mail.com",
  role: "admin"
};

const { nom, age } = user;

console.log(nom);
console.log(age);
Console
Awa
25
✏️ Ligne par ligne
const { nom, age } = user;extrait les clés nom et age dans deux variables distinctes.
nomvaut user.nom, automatiquement.
agevaut user.age, automatiquement.

Renommer et fournir des valeurs par défaut :

JS
let user = { nom: "Awa", age: 25 };

const { nom: fullName, age, pays = "Sénégal" } = user;

console.log(fullName);  // "Awa"
console.log(pays);      // "Sénégal" (valeur par défaut)
Console
Awa
Sénégal

Cas d'usage fréquent — paramètres de fonction :

JS
function afficher({ nom, age }) {
  console.log(`${nom} a ${age} ans`);
}

afficher({ nom: "Awa", age: 25 });
afficher({ nom: "John", age: 30 });
Console
Awa a 25 ans
John a 30 ans
📖 Mots à connaître
destructurationextraire plusieurs propriétés d'un objet en une seule déclaration.
valeur par défautpays = "Sénégal" : utilisée si la clé est absente.
renommernom: fullName : extrait user.nom dans une variable nommée fullName.
⚠️ Pièges fréquents
  • L'ordre n'a pas d'importance pour un objet (contrairement aux tableaux) : { age, nom } fonctionne pareil que { nom, age }.
  • Si la clé n'existe pas et qu'aucune valeur par défaut n'est fournie, la variable vaut undefined.
💡 Astuce

Rappel : voir la fiche 89 sur la destructuration de tableau (basée sur l'ordre) et la fiche 117 sur le spread d'objet pour copier ou fusionner.

12
Chapitre 1232 fiches

Programmation orientée objet

Classes, héritage et prototypes

JS · Fiche Originale

Fiche 117 — Spread avec les objets
💡 En clair

L'opérateur spread ... permet de copier ou fusionner les propriétés d'un objet dans un autre. Très utile pour créer un nouvel objet basé sur un existant, ou pour fusionner deux objets sans modifier l'original.

1) Copier un objet (shallow copy) :

JS
let original = { nom: "Awa", age: 25 };
let copie = { ...original };

copie.age = 30;
console.log(original.age);  // 25 — l'original est intact
console.log(copie.age);     // 30
Console
25
30

2) Fusionner deux objets :

JS
let base = { nom: "Awa", age: 25 };
let infos = { email: "a@b.com", role: "admin" };

let user = { ...base, ...infos };
console.log(user);
Console
{ nom: 'Awa', age: 25, email: 'a@b.com', role: 'admin' }

3) Ajouter/modifier des propriétés lors de la copie :

JS
let user = { nom: "Awa", age: 25 };
let userMAJ = { ...user, age: 26, pays: "Sénégal" };
console.log(userMAJ);
Console
{ nom: 'Awa', age: 26, pays: 'Sénégal' }
✏️ Ligne par ligne
{ ...original }crée un nouvel objet avec toutes les propriétés de original.
{ ...base, ...infos }fusionne les propriétés de base et infos.
{ ...user, age: 26 }copie user et surcharge la propriété age.
📖 Mots à connaître
spreadopérateur ... qui "déplie" les propriétés d'un objet dans un autre.
shallow copycopie en surface — les objets imbriqués sont partagés, pas recopiés.
surchargela dernière clé citée écrase les précédentes en cas de conflit.
⚠️ Pièges fréquents
  • La copie est superficielle : si une propriété est un objet imbriqué, les deux objets partagent cette référence. Pour une copie profonde, utiliser structuredClone() ou JSON.parse(JSON.stringify()).
  • Si deux objets ont la même clé, la dernière gagne : { a: 1, ...{ a: 2 } } donne { a: 2 }.
💡 Astuce

Rappel : voir la fiche 90 sur le spread avec les tableaux (même opérateur, comportement similaire).

JS · Fiche Originale

Fiche 118 — Object.keys() et Object.values()
💡 En clair

Object.keys() renvoie un tableau des clés d'un objet, Object.values() renvoie un tableau des valeurs. Ces méthodes permettent de parcourir un objet avec .forEach(), .map(), .filter()... comme un tableau.

JS
let user = {
  nom: "Awa",
  age: 25,
  email: "awa@mail.com"
};

console.log(Object.keys(user));
console.log(Object.values(user));
Console
[ 'nom', 'age', 'email' ]
[ 'Awa', 25, 'awa@mail.com' ]
✏️ Ligne par ligne
Object.keys(user)renvoie le tableau des clés de l'objet.
Object.values(user)renvoie le tableau des valeurs associées.
Object.entries(user)renvoie un tableau de paires [clé, valeur] — voir fiche 120.

Cas d'usage — parcourir un objet comme un tableau :

JS
let scores = { Awa: 18, John: 14, Maria: 16 };

Object.keys(scores).forEach(nom => {
  console.log(nom + " : " + scores[nom]);
});

// Total des scores
let total = Object.values(scores).reduce((a, b) => a + b, 0);
console.log("Total :", total);
Console
Awa : 18
John : 14
Maria : 16
Total : 48
📖 Mots à connaître
Object.keys()méthode statique qui renvoie les clés d'un objet sous forme de tableau.
Object.values()méthode statique qui renvoie les valeurs d'un objet.
itérationparcourir les propriétés d'un objet via les méthodes de tableau.
⚠️ Pièges fréquents
  • Object.keys() ne renvoie que les propriétés énumérables propres à l'objet — pas celles héritées par prototype.
  • L'ordre des clés n'est pas strictement garanti pour les clés numériques (elles sont triées), contrairement aux clés texte qui suivent l'ordre d'insertion.
💡 Astuce

Rappel : voir la fiche 120 sur Object.entries() pour obtenir un tableau de paires [clé, valeur] — pratique pour tout parcourir en une fois.

JS · Fiche Originale

Fiche 122 — Tester l’existence d’une propriété
💡 En clair

Pour tester l'existence d'une propriété dans un objet, trois approches coexistent : l'opérateur in, hasOwnProperty(), et la comparaison directe à undefined. Toutes ne sont pas équivalentes — il faut connaître les nuances.

JS
let user = { nom: "Awa", age: 25 };

// 1) Opérateur in — teste aussi le prototype
console.log("nom" in user);       // true
console.log("toString" in user);   // true (hérité !)

// 2) hasOwnProperty — uniquement les props propres
console.log(user.hasOwnProperty("nom"));      // true
console.log(user.hasOwnProperty("toString")); // false

// 3) Comparaison à undefined — peu fiable
console.log(user.nom !== undefined);       // true
console.log(user.email !== undefined);     // false (absente)
console.log(user.age !== undefined);       // true, mais... et si age valait undefined ?
Console
true
true
true
false
true
false
true
✏️ Ligne par ligne
"nom" in uservrai si la clé existe sur l'objet OU son prototype.
user.hasOwnProperty("nom")vrai seulement si la clé est propre à user (pas héritée).
user.nom !== undefinedfaux si la clé est absente OU si elle existe mais vaut undefined — ambigu.
📖 Mots à connaître
inopérateur qui teste l'existence d'une clé (propre ou héritée).
hasOwnProperty()méthode qui ne teste que les propriétés propres (non héritées).
propres vs héritéespropres = déclarées sur l'objet ; héritées = viennent du prototype.
⚠️ Pièges fréquents
  • Comparer à undefined est ambigu : si une clé existe mais vaut explicitement undefined, le test échoue alors que la clé existe.
  • "toString" in user renvoie true même sans l'avoir défini — car toString est hérité d'Object.prototype.
💡 Astuce

Recommandation : hasOwnProperty() est le test le plus sûr. Voir la fiche 152 sur hasOwnProperty() et la fiche 142 sur les prototypes.

JS · Fiche Originale

Fiche 123 — Object.freeze() et Object.seal()
💡 En clair

Object.freeze() rend un objet totalement immuable : on ne peut plus ajouter, modifier ni supprimer de propriétés. Object.seal() est plus permissif : on ne peut ni ajouter ni supprimer, mais on peut modifier les propriétés existantes.

JS
let config1 = Object.freeze({ version: "1.0", env: "prod" });
config1.version = "2.0";          // ❌ ignoré en mode strict
config1.nouveau = "test";          // ❌ ignoré
delete config1.env;                // ❌ ignoré
console.log(config1);              // inchangé

let config2 = Object.seal({ version: "1.0", env: "prod" });
config2.version = "2.0";           // ✅ autorisé
config2.nouveau = "test";          // ❌ ignoré
delete config2.env;                // ❌ ignoré
console.log(config2);
Console
{ version: '1.0', env: 'prod' }
{ version: '2.0', env: 'prod' }
✏️ Ligne par ligne
Object.freeze(obj)gèle : aucune modification possible (ajout, modif, suppression).
Object.seal(obj)scelle : modif autorisée, mais pas d'ajout ni suppression.
config1.version = "2.0"silencieusement ignoré en mode non-strict, erreur en mode strict.

Pour vérifier l'état d'un objet :

JS
let obj = Object.freeze({ a: 1 });
console.log(Object.isFrozen(obj));  // true
console.log(Object.isSealed(obj));  // true aussi (frozen implique sealed)

let obj2 = Object.seal({ a: 1 });
console.log(Object.isFrozen(obj2)); // false
console.log(Object.isSealed(obj2)); // true
Console
true
true
false
true
📖 Mots à connaître
Object.freeze()gèle un objet — toute modification est bloquée.
Object.seal()scelle un objet — modifications autorisées, pas d'ajout/suppression.
immutabilitéun objet qu'on ne peut plus modifier après création — safer code.
⚠️ Pièges fréquents
  • Le gel est superficiel : Object.freeze({ user: { age: 25 } }) ne gèle pas user.age. Pour un gel profond, utiliser une fonction récursive ou structuredClone après freeze.
  • En mode strict ("use strict"), tenter de modifier un objet gelé lève une TypeError. En mode non-strict, l'erreur est silencieuse.
💡 Astuce

Cas d'usage : figer une configuration, des constantes ou un état partagé pour éviter les modifications accidentelles.

JS · Fiche Originale

Fiche 125 — JavaScript et POO
💡 En clair

La programmation orientée objet (POO) organise le code autour d'objets qui regroupent données et comportements. Au lieu de fonctions et variables isolées, on pense « entités » : un Utilisateur a un nom et sait se présenter.

Sans POO — données et fonctions séparées :

JS
let nom1 = "Awa", age1 = 25;
let nom2 = "Moussa", age2 = 30;

function presenter1() {
  console.log(nom1 + " a " + age1 + " ans");
}
function presenter2() {
  console.log(nom2 + " a " + age2 + " ans");
}

Avec POO — une classe factorise la logique :

JS
class Utilisateur {
  constructor(nom, age) {
    this.nom = nom;
    this.age = age;
  }
  presenter() {
    console.log(this.nom + " a " + this.age + " ans");
  }
}

let awa = new Utilisateur("Awa", 25);
awa.presenter();
Console
Awa a 25 ans
📖 Mots à connaître
classemodèle qui décrit la structure et les comportements.
instanceobjet concret créé à partir d'une classe.
Encapsulationregrouper données et méthodes dans un même objet.
💡 Astuce

Les 4 piliers de la POO : encapsulation, héritage, polymorphisme, abstraction. JavaScript les met en œuvre via les classes (et les prototypes en dessous).

JS · Fiche Originale

Fiche 126 — Créer une classe
💡 En clair

Une classe est un modèle (un moule) qui permet de créer plusieurs objets partageant la même structure et les mêmes méthodes. Elle se déclare avec le mot-clé class, et sert à instancier des objets via new.

JS
class Personne {
  constructor(nom, age) {
    this.nom = nom;
    this.age = age;
  }

  saluer() {
    return "Bonjour, je suis " + this.nom;
  }
}

let user1 = new Personne("Awa", 25);
let user2 = new Personne("John", 30);

console.log(user1.saluer());
console.log(user2.saluer());
Console
Bonjour, je suis Awa
Bonjour, je suis John
✏️ Ligne par ligne
class Personne { ... }déclare la classe — un moule à objets.
constructor(nom, age) { ... }méthode spéciale appelée à l'instanciation — voir fiche 127.
new Personne("Awa", 25)crée une instance de Personne avec ces valeurs.
user1.saluer()appelle la méthode saluer de l'instance.

Convention : les noms de classes commencent par une majuscule (PascalCase) :

JS
class CompteBancaire { ... }
class UtilisateurAdmin { ... }
// Pas de "class utilisateur" ou "class Utilisateur_admin"
📖 Mots à connaître
classeun modèle qui décrit la structure et le comportement d'un type d'objet.
instanceun objet créé à partir d'une classe (avec new).
méthodeune fonction déclarée dans une classe, appelable sur chaque instance.
⚠️ Pièges fréquents
  • Les classes ne sont pas hissées (hoisting) comme les fonctions : on ne peut pas les utiliser avant leur déclaration dans le code.
  • Une classe doit être instanciée avec new — appeler Personne("Awa", 25) sans new lève une TypeError.
💡 Astuce

Rappel : voir la fiche 127 sur le constructor et la fiche 130 sur new. La fiche 153 explique la relation entre classes et prototypes.

JS · Fiche Originale

Fiche 127 — constructor
💡 En clair

Le constructor est une méthode spéciale appelée automatiquement quand on crée une instance avec new. Il initialise les propriétés de l'objet en recevant les arguments passés à new. C'est le "setup" de l'instance.

JS
class Personne {
  constructor(nom, age, ville) {
    this.nom = nom;
    this.age = age;
    this.ville = ville;
    this.creeLe = new Date();
  }
}

let user = new Personne("Awa", 25, "Dakar");
console.log(user.nom);
console.log(user.creeLe);
Console
Awa
2024-... (date actuelle)
✏️ Ligne par ligne
constructor(nom, age, ville)reçoit les arguments de new Personne(...).
this.nom = nom;initialise la propriété nom de l'instance.
this.creeLe = new Date();ajoute une propriété calculée automatiquement.

On peut définir des valeurs par défaut ou appeler des méthodes :

JS
class Compte {
  constructor(titulaire, solde = 0) {
    this.titulaire = titulaire;
    this.solde = solde;
    this.historique = [];
    this.enregistrer("Ouverture", solde);
  }
  enregistrer(action, montant) {
    this.historique.push({ action, montant, date: new Date() });
  }
}

let c = new Compte("Awa", 100);
console.log(c.historique.length);
Console
1
📖 Mots à connaître
constructorméthode d'initialisation appelée à chaque new.
thisdans le constructor, désigne la nouvelle instance en cours de création.
initialisationmise en place des valeurs initiales de l'instance.
⚠️ Pièges fréquents
  • Une classe ne peut avoir qu'un seul constructor. En avoir plusieurs provoque une SyntaxError.
  • Si on ne définit pas de constructor, un constructor par défaut (vide) est utilisé — l'instance n'aura aucune propriété tant qu'on ne l'affecte pas.
💡 Astuce

Rappel : voir la fiche 126 sur la déclaration de classe et la fiche 128 sur les attributs.

JS · Fiche Originale

Fiche 128 — Attributs
💡 En clair

Les attributs (ou propriétés d'instance) sont les variables stockées sur chaque objet. Ils représentent l'état de l'instance : ce qui la distingue des autres objets de la même classe. Chaque instance a ses propres valeurs d'attributs.

JS
class Personne {
  constructor(nom, age) {
    this.nom = nom;     // attribut
    this.age = age;     // attribut
  }
}

let p1 = new Personne("Awa", 25);
let p2 = new Personne("John", 30);

console.log(p1.nom, p1.age);
console.log(p2.nom, p2.age);

// Chaque instance a SES propres attributs
p1.age = 26;
console.log(p2.age);  // toujours 30
Console
Awa 25
John 30
30
✏️ Ligne par ligne
this.nom = nom;chaque instance aura sa propre propriété nom.
p1.age = 26;modifie uniquement l'attribut de p1, pas de p2.
console.log(p2.age)renvoie 30 — preuve que les attributs sont indépendants.

On peut ajouter des attributs après l'instanciation, mais ce n'est pas recommandé :

JS
let p = new Personne("Awa", 25);
p.email = "awa@mail.com";  // ajout dynamique
console.log(p.email);      // "awa@mail.com"
// ⚠️ mais un autre instance n'aura pas .email
Console
awa@mail.com
📖 Mots à connaître
attributpropriété propre à chaque instance, définie dans le constructor.
étatl'ensemble des valeurs des attributs d'une instance à un instant donné.
instanceun objet créé à partir d'une classe, avec ses propres valeurs d'attributs.
⚠️ Pièges fréquents
  • Ajouter des attributs dynamiquement après l'instanciation est découragé : cela rend les instances hétérogènes et casse la cohérence de la classe.
  • Les attributs déclarés avec this. sont publics par défaut. Pour les rendre privés, voir la fiche 133 sur les champs privés #.
💡 Astuce

Rappel : voir la fiche 127 sur le constructor (où on initialise les attributs) et la fiche 133 sur les champs privés pour l'encapsulation.

JS · Fiche Originale

Fiche 130 — new
💡 En clair

Le mot-clé new crée une nouvelle instance d'une classe. Il effectue 4 opérations : (1) crée un objet vide, (2) lie this à cet objet, (3) appelle le constructor, (4) renvoie l'objet créé. Sans new, le constructor échoue.

JS
class Personne {
  constructor(nom) {
    this.nom = nom;
    console.log("Instance créée pour " + nom);
  }
}

let p1 = new Personne("Awa");
let p2 = new Personne("John");

console.log(p1 instanceof Personne);  // true
console.log(p1 === p2);              // false (2 instances distinctes)
Console
Instance créée pour Awa
Instance créée pour John
true
false
✏️ Ligne par ligne
new Personne("Awa")crée un nouvel objet, lie this, appelle le constructor.
p1 instanceof Personnevérifie que p1 est une instance de Personne — voir fiche 139.
p1 === p2faux : deux instances sont des objets distincts.

Sans new — erreur ou comportement inattendu :

JS
class Personne {
  constructor(nom) { this.nom = nom; }
}

let p = Personne("Awa");  // ❌ TypeError en mode strict
// ou : this = window/global, propriétés collées n'importe où
Console
TypeError: Cannot set properties of undefined
📖 Mots à connaître
newopérateur qui instancie une classe — crée un nouvel objet et lie this.
instanceobjet créé par new, possédant les propriétés et méthodes de la classe.
instanceofopérateur qui vérifie qu'un objet est instance d'une classe — voir fiche 139.
⚠️ Pièges fréquents
  • Oublier new provoque une TypeError en mode strict (recommandé). En mode non-strict, this devient l'objet global — bug très sournois.
  • new ne peut être utilisé qu'avec une fonction constructeur ou une classe — pas avec une arrow function.
💡 Astuce

Rappel : voir la fiche 126 sur la déclaration de classe, la fiche 127 sur le constructor, et la fiche 139 sur instanceof.

JS · Fiche Originale

Fiche 131 — Méthodes d’instance
💡 En clair

Une méthode d'instance est une fonction déclarée dans une classe, accessible sur chaque instance. Elle est stockée dans le prototype de la classe : toutes les instances partagent la même méthode (économie de mémoire).

JS
class CompteBancaire {
  constructor(solde) {
    this.solde = solde;
  }
  deposer(montant) {
    this.solde += montant;
  }
  retirer(montant) {
    this.solde -= montant;
  }
  afficherSolde() {
    console.log("Solde : " + this.solde);
  }
}

let compte = new CompteBancaire(100);
compte.deposer(50);
compte.afficherSolde();
compte.retirer(30);
compte.afficherSolde();
Console
Solde : 150
Solde : 120
✏️ Ligne par ligne
deposer(montant) { ... }méthode d'instance — déclarée dans la classe.
compte.deposer(50);appel : this = compte.
this.solde += montantmodifie l'attribut solde de cette instance précise.
💡 Astuce

Les méthodes d'instance sont partagées entre toutes les instances via le prototype : 1000 objets n'ont qu'une seule copie de chaque méthode en mémoire.

JS · Fiche Originale

Fiche 132 — static
💡 En clair

Le mot-clé static permet de définir des méthodes de classe : elles sont appelées sur la classe elle-même, pas sur une instance. Utile pour des utilitaires (helpers), des factories, ou des méthodes qui ne dépendent pas de l'état d'une instance.

JS
class MathUtils {
  static carre(x) {
    return x * x;
  }
  static aireCercle(r) {
    return Math.PI * this.carre(r);
  }
}

// Appel sur la classe, pas sur une instance
console.log(MathUtils.carre(5));
console.log(MathUtils.aireCercle(2));
Console
25
12.566370614359172
✏️ Ligne par ligne
static carre(x)méthode statique — pas de this représentant une instance.
MathUtils.carre(5)appel via la classe, pas via un objet.
this.carre(r) dans aireCerclethis désigne la classe MathUtils, pas une instance.

Cas d'usage — factory méthode :

JS
class User {
  constructor(nom, role) {
    this.nom = nom;
    this.role = role;
  }
  static admin(nom) {
    return new User(nom, "admin");
  }
}

let a = User.admin("Awa");
console.log(a.role);
Console
admin
📖 Mots à connaître
staticmot-clé pour une méthode (ou propriété) rattachée à la classe, pas aux instances.
méthode de classeméthode appelée sur la classe — Classe.methode().
factoryméthode statique qui crée et renvoie une instance — alternative au constructor.
⚠️ Pièges fréquents
  • Une méthode statique ne peut pas utiliser this.nom pour accéder à une propriété d'instance — this désigne la classe.
  • Appeler une méthode statique sur une instance provoque une TypeError : user.carre(5) ne fonctionne pas, il faut User.carre(5).
💡 Astuce

Exemples connus : Object.keys(), Array.from(), Math.max() sont toutes des méthodes statiques — appelées sur la classe.

JS · Fiche Originale

Fiche 134 — Encapsulation
💡 En clair

L'encapsulation consiste à cacher les détails internes d'un objet et n'exposer que les méthodes utiles. Les champs privés (préfixe #) rendent un attribut inaccessible de l'extérieur : on ne peut le modifier qu'à travers des méthodes contrôlées.

JS
class CompteBancaire {
  #solde = 0;

  deposer(montant) {
    if (montant > 0) {
      this.#solde += montant;
    }
  }
  retirer(montant) {
    if (montant > 0 && montant <= this.#solde) {
      this.#solde -= montant;
    }
  }
  getSolde() {
    return this.#solde;
  }
}

let compte = new CompteBancaire();
compte.deposer(100);
compte.retirer(30);
console.log(compte.getSolde());
Console
70
✏️ Ligne par ligne
#solde = 0;champ privé — inaccessible depuis l'extérieur.
deposer(montant) { if (montant > 0) ... }contrôle : on ne dépose que des montants positifs.
compte.#solde = 1000000;❌ impossible — le # protège la donnée.
⚠️ Pièges fréquents
  • Sans encapsulation, n'importe qui peut faire compte.solde = -999 : la donnée perd son intégrité.
  • Le # est obligatoire pour déclarer un champ privé — pas seulement à l'usage.

JS · Fiche Originale

Fiche 135 — extends
💡 En clair

Le mot-clé extends permet de créer une classe qui hérite d'une autre. La classe enfant récupère toutes les propriétés et méthodes de la classe parent, et peut en ajouter de nouvelles ou redéfinir les existantes. C'est le pilier de la POO.

JS
class Animal {
  constructor(nom) {
    this.nom = nom;
  }
  deplacer() {
    return this.nom + " se déplace";
  }
}

class Chien extends Animal {
  aboyer() {
    return this.nom + " dit : Wouf !";
  }
}

let rex = new Chien("Rex");
console.log(rex.deplacer());  // hérité
console.log(rex.aboyer());    // propre à Chien
Console
Rex se déplace
Rex dit : Wouf !
✏️ Ligne par ligne
class Chien extends AnimalChien hérite de Animal — toutes ses méthodes sont disponibles.
rex.deplacer()méthode héritée d'Animal, appelable sur une instance de Chien.
rex.aboyer()méthode propre à Chien — pas sur les autres animaux.

On peut hériter en chaîne (grand-parent → parent → enfant) :

JS
class Vehicule { constructor() { this.roues = 0; } }
class Voiture extends Vehicule { constructor() { super(); this.roues = 4; } }
class Taxi extends Voiture { constructor() { super(); this.tarif = 1.5; } }

let t = new Taxi();
console.log(t.roues);   // 4 (hérité)
console.log(t.tarif);   // 1.5
Console
4
1.5
📖 Mots à connaître
extendsmot-clé pour qu'une classe hérite d'une autre.
classe parentla classe dont on hérite (aussi appelée superclasse).
classe enfantla classe qui hérite (aussi appelée sous-classe).
⚠️ Pièges fréquents
  • Dans le constructor d'une classe enfant, on doit appeler super() avant d'utiliser this — sinon ReferenceError.
  • L'héritage multiple n'existe pas en JS : une classe ne peut extends qu'une seule autre classe.
💡 Astuce

Rappel : voir la fiche 136 sur super (appel du parent) et la fiche 137 sur la redéfinition de méthode.

JS · Fiche Originale

Fiche 136 — super
💡 En clair

Le mot-clé super permet d'appeler le constructor ou les méthodes de la classe parent depuis une classe enfant. C'est obligatoire dans le constructor d'une sous-classe avant tout usage de this.

JS
class Animal {
  constructor(nom) {
    this.nom = nom;
  }
  deplacer() { return this.nom + " se déplace"; }
}

class Oiseau extends Animal {
  constructor(nom, envergure) {
    super(nom);             // appelle Animal.constructor(nom)
    this.envergure = envergure;
  }
  deplacer() {
    return super.deplacer() + " en volant";  // appelle Animal.deplacer()
  }
}

let a = new Oiseau("Piou", 30);
console.log(a.deplacer());
Console
Piou se déplace en volant
✏️ Ligne par ligne
super(nom)appelle le constructor parent avec l'argument nom.
this.envergure = envergure;ne peut être fait qu'APRÈS super().
super.deplacer()appelle la méthode deplacer() du parent — pour réutiliser son code.

Sans super() dans le constructor enfant — erreur :

JS
class B extends A {
  constructor(x) {
    this.x = x;  // ❌ ReferenceError : must call super first
  }
}
Console
ReferenceError: must call super constructor before accessing this
📖 Mots à connaître
super()appel au constructor du parent — obligatoire dans un constructor enfant.
super.methode()appel à une méthode du parent depuis une redéfinition.
redéfinitionredéfinir une méthode héritée — voir la fiche 137.
⚠️ Pièges fréquents
  • Oublier super() dans le constructor d'une sous-classe provoque une ReferenceError dès qu'on touche this.
  • Appeler super.method() en dehors d'une méthode ou après l'avoir redéfinie n'a pas toujours le comportement attendu — bien réfléchir au flux.
💡 Astuce

Rappel : voir la fiche 135 sur extends (héritage) et la fiche 137 sur la redéfinition qui s'appuie souvent sur super.

JS · Fiche Originale

Fiche 137 — Redéfinition de méthode
💡 En clair

La redéfinition de méthode (override) consiste à réécrire, dans une classe enfant, une méthode déjà présente dans la classe parent. L'enfant fournit alors sa propre version, tout en pouvant appeler la version du parent via super.

JS
class Animal {
  crier() { return "..."; }
  decrire() { return "Animal fait " + this.crier(); }
}

class Chien extends Animal {
  crier() { return "Wouf !"; }  // redéfinition
}

class Chat extends Animal {
  crier() { return "Miaou !"; }  // autre redéfinition
}

console.log(new Chien().decrire());
console.log(new Chat().decrire());
Console
Animal fait Wouf !
Animal fait Miaou !
✏️ Ligne par ligne
crier() dans Chienredéfinit la méthode héritée d'Animal.
this.crier() dans decrire()appelle la BONNE version : celle de Chien si l'instance est un Chien.
new Chien().decrire()decrire hérité + crier redéfini → polymorphisme.

Combiner avec super pour étendre le comportement :

JS
class Vehicule {
  demarrer() { return "Moteur allumé"; }
}

class VoitureElectrique extends Vehicule {
  demarrer() {
    return super.demarrer() + " (silencieusement)";
  }
}

console.log(new VoitureElectrique().demarrer());
Console
Moteur allumé (silencieusement)
📖 Mots à connaître
overrideredéfinir une méthode héritée dans une sous-classe.
super.methode()appeler la version parente depuis la redéfinition.
polymorphismeune même méthode se comporte différemment selon la classe — voir fiche 138.
⚠️ Pièges fréquents
  • Pour que la redéfinition fonctionne, il faut exactement le même nom de méthode. Une faute de frappe crée une nouvelle méthode au lieu de redéfinir.
  • Si on oublie super dans une redéfinition, on perd l'accès au comportement du parent — parfois voulu, parfois un bug.
💡 Astuce

Rappel : voir la fiche 135 sur extends, la fiche 136 sur super, et la fiche 138 sur le polymorphisme.

JS · Fiche Originale

Fiche 138 — Polymorphisme
💡 En clair

Le polymorphisme (du grec "plusieurs formes") est la capacité d'une même méthode à se comporter différemment selon la classe de l'objet qui l'appelle. Grâce à l'héritage et la redéfinition, on peut traiter plusieurs types d'objets de façon uniforme.

JS
class Forme {
  aire() { return 0; }
}

class Carre extends Forme {
  constructor(c) { super(); this.c = c; }
  aire() { return this.c * this.c; }
}

class Cercle extends Forme {
  constructor(r) { super(); this.r = r; }
  aire() { return Math.PI * this.r * this.r; }
}

const formes = [new Carre(4), new Cercle(3), new Carre(2)];
formes.forEach(f => console.log(f.aire()));
Console
16
28.274333882308138
4
✏️ Ligne par ligne
aire() dans Carrecalcule c×c — redéfinition de la méthode.
aire() dans Cerclecalcule π×r² — autre redéfinition.
formes.forEach(f => f.aire())appelle la BONNE méthode selon le type de f — polymorphisme.

Le polymorphisme simplifie le code appelant :

JS
function afficherAire(forme) {
  console.log("Aire = " + forme.aire());
}

afficherAire(new Carre(5));
afficherAire(new Cercle(2));
// pas besoin de if/else ou instanceof — la méthode sait que faire
Console
Aire = 25
Aire = 12.566370614359172
📖 Mots à connaître
polymorphismeune même méthode, plusieurs comportements selon la classe.
overrideredéfinition d'une méthode dans une sous-classe — voir fiche 137.
traitement uniformeappeler .aire() sans connaître le type exact de l'objet.
⚠️ Pièges fréquents
  • Le polymorphisme ne fonctionne que si toutes les classes implémentent la même méthode avec la même signature. Sinon, on tombe sur undefined ou TypeError.
  • Abuser de instanceof pour distinguer les types casse le polymorphisme — préférer des méthodes redéfinies.
💡 Astuce

Rappel : voir la fiche 137 sur la redéfinition et la fiche 139 sur instanceof — qui sert à vérifier un type quand le polymorphisme ne suffit pas.

JS · Fiche Originale

Fiche 139 — instanceof
💡 En clair

L'opérateur instanceof vérifie qu'un objet est une instance d'une classe donnée (ou d'une de ses classes parentes). Il renvoie true ou false. Très utile pour adapter le comportement selon le type réel d'un objet.

JS
class Animal {}
class Chien extends Animal {}
class Chat extends Animal {}

let rex = new Chien();
let felix = new Chat();

console.log(rex instanceof Chien);    // true
console.log(rex instanceof Animal);   // true (héritage)
console.log(rex instanceof Chat);     // false
console.log(rex instanceof Object);   // true (tout objet hérite d'Object)
Console
true
true
false
true
✏️ Ligne par ligne
rex instanceof Chienvrai : rex est créé à partir de Chien.
rex instanceof Animalvrai : Chien hérite d'Animal.
rex instanceof Chatfaux : rex n'est pas un Chat.
rex instanceof Objectvrai : tout objet JS hérite d'Object.

Cas d'usage — vérifier le type avant d'agir :

JS
function decrire(animal) {
  if (animal instanceof Chien) return "C'est un chien";
  if (animal instanceof Chat)  return "C'est un chat";
  return "Animal inconnu";
}

console.log(decrire(new Chien()));
console.log(decrire(new Chat()));
Console
C'est un chien
C'est un chat
📖 Mots à connaître
instanceofopérateur qui teste la chaîne de prototypes d'un objet.
type à l'exécutionvérifier la classe réelle d'un objet, pas sa variable.
héritageun enfant est aussi instanceof son parent.
⚠️ Pièges fréquents
  • instanceof ne fonctionne qu'avec des objets — pas avec les primitives. 5 instanceof Number renvoie false (sauf si new Number(5)).
  • Pour les primitives, utiliser typeof : typeof 5 === "number".
💡 Astuce

Rappel : voir la fiche 14 sur typeof (pour primitives) et la fiche 138 sur le polymorphisme qui réduit le besoin d'instanceof.

JS · Fiche Originale

Fiche 140 — Getters
💡 En clair

Un getter est une méthode précédée du mot-clé get qui s'utilise comme une propriété (sans parenthèses). Il permet de calculer une valeur à la volée tout en gardant une syntaxe d'accès simple : obj.prop au lieu de obj.prop().

JS
class Personne {
  constructor(nom, naissance) {
    this.nom = nom;
    this.naissance = naissance;
  }
  get age() {
    const annee = new Date().getFullYear();
    return annee - this.naissance;
  }
}

let p = new Personne("Awa", 1999);
console.log(p.age);  // pas de parenthèses !
Console
26
✏️ Ligne par ligne
get age() { ... }déclare un getter — accessible comme une propriété.
p.agepas de parenthèses — le getter est appelé automatiquement.
return annee - this.naissance;calcule l'âge dynamiquement, sans le stocker.

Le getter peut aussi encapsuler un attribut privé :

JS
class Compte {
  #solde = 0;  // champ privé
  deposer(montant) { this.#solde += montant; }
  get solde() { return this.#solde; }
}

let c = new Compte();
c.deposer(100);
console.log(c.solde);  // 100 — lecture via getter, écriture bloquée
Console
100
📖 Mots à connaître
getmot-clé pour déclarer un getter — méthode appelée comme une propriété.
propriété calculéevaleur dérivée d'autres propriétés, recalculée à chaque accès.
encapsulationexposer une valeur en lecture sans permettre l'écriture directe.
⚠️ Pièges fréquents
  • Le getter ne doit pas avoir de paramètres — sinon SyntaxError.
  • Ne pas confondre avec une méthode : p.age() provoque une TypeError car p.age est déjà le résultat du getter.
💡 Astuce

Rappel : voir la fiche 141 sur les setters (modification contrôlée) et la fiche 133 sur les champs privés #.

JS · Fiche Originale

Fiche 141 — Setters
💡 En clair

Un setter est une méthode précédée du mot-clé set qui s'utilise comme une affectation de propriété. Il permet de valider ou transformer une valeur avant de l'affecter, sans exposer l'attribut sous-jacent.

JS
class Personne {
  constructor(nom) { this.nom = nom; }
  set nom(valeur) {
    if (valeur.length < 2) throw new Error("Nom trop court");
    this._nom = valeur;
  }
  get nom() { return this._nom; }
}

let p = new Personne("Awa");
p.nom = "Mariama";       // OK
console.log(p.nom);
p.nom = "X";             // ❌ Erreur : Nom trop court
Console
Mariama
Error: Nom trop court
✏️ Ligne par ligne
set nom(valeur) { ... }déclare un setter — appelé lors d'une affectation.
p.nom = "Mariama"appelle set nom("Mariama") — pas d'accès direct à _nom.
if (valeur.length < 2) throw ...valide avant d'affecter — protège l'attribut.

Combinaison getter/setter pour encapsuler un champ privé :

JS
class Thermostat {
  #temperature = 20;
  get temperature() { return this.#temperature; }
  set temperature(valeur) {
    if (valeur < 10) valeur = 10;
    if (valeur > 30) valeur = 30;
    this.#temperature = valeur;
  }
}

let t = new Thermostat();
t.temperature = 50;       // sera plafonnée à 30
console.log(t.temperature);
Console
30
📖 Mots à connaître
setmot-clé pour déclarer un setter — méthode appelée lors d'une affectation.
validationvérifier la valeur avant de l'affecter — empêcher les états invalides.
encapsulationcacher l'attribut réel et exposer un setter/getter contrôlé.
⚠️ Pièges fréquents
  • Le setter doit avoir exactement un paramètre — sinon SyntaxError.
  • Un setter sans getter correspondant rend la propriété "write-only" — possible mais rare et parfois source d'erreurs.
💡 Astuce

Rappel : voir la fiche 140 sur les getters et la fiche 133 sur les champs privés pour bien encapsuler les attributs.

JS · Fiche Originale

Fiche 142 — Pourquoi les prototypes ?
💡 En clair

Les prototypes sont le mécanisme par lequel JavaScript permet à un objet d'hériter des propriétés d'un autre. Chaque objet a un prototype caché ; quand on cherche une propriété, JS remonte la chaîne des prototypes jusqu'à la trouver. Les classes sont du "sucre syntaxique" par-dessus ce mécanisme.

JS
let animal = {
  respirer() { return "Je respire"; }
};

let chien = Object.create(animal);  // chien hérite d'animal
chien.aboyer = () => "Wouf";

console.log(chien.aboyer());   // propre
console.log(chien.respirer()); // hérité via prototype !
Console
Wouf
Je respire
✏️ Ligne par ligne
Object.create(animal)crée un objet dont le prototype est animal.
chien.aboyer()méthode propre à chien.
chien.respirer()non définie sur chien — JS cherche dans le prototype animal.

Tout objet possède un prototype — y compris les tableaux :

JS
let fruits = ["pomme", "banane"];
console.log(typeof fruits.push);      // "function" — héritée
console.log(typeof fruits.toString); // "function" — héritée d'Object
Console
function
function
📖 Mots à connaître
prototypeobjet partagé par plusieurs instances — source des propriétés héritées.
chaîne des prototypessuite de prototypes parcourue quand une propriété est cherchée.
sucre syntaxiqueles classes sont une syntaxe plus claire au-dessus du mécanisme prototypes.
⚠️ Pièges fréquents
  • Modifier Object.prototype directement est très dangereux — cela affecte tous les objets du programme et peut casser les boucles for...in.
  • Les classes modernes rendent les prototypes quasi invisibles — il est rare d'y toucher directement aujourd'hui.
💡 Astuce

Rappel : voir la fiche 143 sur le prototype d'un objet, la fiche 144 sur la chaîne des prototypes, et la fiche 153 sur classe vs prototype.

JS · Fiche Originale

Fiche 143 — Prototype d’un objet
💡 En clair

Le prototype d'un objet est l'objet caché duquel il hérite ses propriétés. On peut y accéder via Object.getPrototypeOf(obj) ou obj.__proto__ (à éviter). C'est lui qui contient les méthodes partagées par toutes les instances d'une classe.

JS
class Personne {
  saluer() { return "Bonjour"; }
}

let p = new Personne();

console.log(typeof p.saluer);  // "function" — héritée du prototype
console.log(p.hasOwnProperty("saluer"));  // false — pas sur l'instance

let proto = Object.getPrototypeOf(p);
console.log(proto === Personne.prototype);  // true
Console
function
false
true
✏️ Ligne par ligne
p.saluerméthode trouvée dans le prototype, pas directement sur l'instance p.
p.hasOwnProperty("saluer")faux : la méthode est sur le prototype, pas sur p.
Object.getPrototypeOf(p)récupère le prototype caché de p — voir fiche 145.

Toutes les instances d'une classe partagent le MÊME prototype :

JS
let p1 = new Personne();
let p2 = new Personne();

console.log(Object.getPrototypeOf(p1) === Object.getPrototypeOf(p2));  // true
// une seule méthode saluer en mémoire, partagée
Console
true
📖 Mots à connaître
prototypeobjet partagé contenant les méthodes d'une classe.
Object.getPrototypeOf()méthode standard pour lire le prototype — voir fiche 145.
__proto__propriété obsolète d'accès au prototype — éviter en production.
⚠️ Pièges fréquents
  • Ne pas confondre Personne.prototype (le prototype des instances) avec Object.getPrototypeOf(Personne) (le prototype de la classe elle-même, qui pointe vers Function.prototype).
  • Modifier directement __proto__ est déprécié et lent — toujours passer par Object.create ou les classes.
💡 Astuce

Rappel : voir la fiche 142 sur pourquoi les prototypes, la fiche 144 sur la chaîne des prototypes, et la fiche 145 sur Object.getPrototypeOf().

JS · Fiche Originale

Fiche 144 — Chaîne des prototypes
💡 En clair

La chaîne des prototypes (prototype chain) est le parcours que fait JavaScript quand on cherche une propriété sur un objet : il regarde d'abord l'objet, puis son prototype, puis le prototype du prototype, et ainsi de suite jusqu'à null. C'est ce qui permet l'héritage en JavaScript.

JS
class Animal { respirer() { return "respire"; } }
class Chien extends Animal { aboyer() { return "Wouf"; } }

let rex = new Chien();

console.log(rex.aboyer());    // trouvé sur Chien.prototype
console.log(rex.respirer());  // trouvé sur Animal.prototype
console.log(rex.toString());   // trouvé sur Object.prototype
console.log(rex.inconnue);    // undefined — fin de chaîne
Console
Wouf
respire
[object Object]
undefined
✏️ Ligne par ligne
rex.aboyer()trouvé immédiatement sur Chien.prototype.
rex.respirer()pas sur Chien → remonte à Animal.prototype.
rex.toString()pas sur Chien ni Animal → remonte à Object.prototype.
rex.inconnuepas trouvée → renvoie undefined sans erreur.

La chaîne se termine toujours par null :

JS
let obj = {};
let proto1 = Object.getPrototypeOf(obj);  // Object.prototype
let proto2 = Object.getPrototypeOf(proto1); // null — fin de chaîne
console.log(proto2);
Console
null
📖 Mots à connaître
chaîne des prototypessuite de prototypes parcourus lors de la recherche d'une propriété.
Object.prototypeprototype racine de tous les objets — contient toString, hasOwnProperty...
nullmarqueur de fin de chaîne — au-delà, plus de prototype.
⚠️ Pièges fréquents
  • Une chaîne trop longue peut ralentir la recherche de propriétés — à garder en tête pour les hiérarchies profondes.
  • Si on cherche une propriété inexistante, on obtient undefined sans erreur — c'est pratique mais peut masquer des bugs.
💡 Astuce

Rappel : voir la fiche 142 sur pourquoi les prototypes, la fiche 143 sur le prototype d'un objet, et la fiche 151 sur la recherche d'une propriété.

JS · Fiche Originale

Fiche 145 — Object.getPrototypeOf()
💡 En clair

Object.getPrototypeOf(obj) renvoie le prototype d'un objet. C'est la méthode standard (ES5) pour inspecter la chaîne des prototypes, sans passer par la propriété obsolète __proto__.

JS
class Animal { respirer() {} }
class Chien extends Animal { aboyer() {} }

let rex = new Chien();

let proto1 = Object.getPrototypeOf(rex);
console.log(proto1 === Chien.prototype);  // true

let proto2 = Object.getPrototypeOf(proto1);
console.log(proto2 === Animal.prototype);  // true

let proto3 = Object.getPrototypeOf(proto2);
console.log(proto3 === Object.prototype);  // true

let proto4 = Object.getPrototypeOf(proto3);
console.log(proto4);                       // null
Console
true
true
true
null
✏️ Ligne par ligne
Object.getPrototypeOf(rex)renvoie Chien.prototype — le prototype direct de rex.
Object.getPrototypeOf(proto1)remonte d'un niveau : Animal.prototype.
Object.getPrototypeOf(proto3)remonte encore : Object.prototype.
Object.getPrototypeOf(proto4) === nullfin de la chaîne — plus rien au-dessus.

Vérifier une relation d'héritage :

JS
let rex = new Chien();

console.log(rex instanceof Chien);   // true
console.log(Object.getPrototypeOf(rex) === Chien.prototype);  // true — équivalent
console.log(Object.getPrototypeOf(rex) === Animal.prototype);  // false — niveau direct seulement
Console
true
true
false
📖 Mots à connaître
Object.getPrototypeOf()méthode standard pour lire le prototype d'un objet.
Object.setPrototypeOf()méthode pour modifier le prototype — à éviter pour des raisons de perf.
__proto__propriété obsolète — préférer Object.getPrototypeOf.
⚠️ Pièges fréquents
  • Modifier le prototype après création (Object.setPrototypeOf) est très lent et déconseillé — préférer Object.create() ou les classes dès le départ.
  • Object.getPrototypeOf([]) renvoie Array.prototype, pas Object.prototype — la chaîne passe par Array.prototype en premier.
💡 Astuce

Rappel : voir la fiche 144 sur la chaîne des prototypes et la fiche 146 sur Object.create() pour créer un objet avec un prototype choisi.

JS · Fiche Originale

Fiche 146 — Object.create()
💡 En clair

Object.create(proto) crée un nouvel objet dont le prototype est proto. C'est la méthode standard pour créer un objet qui hérite directement d'un autre, sans passer par une classe. Utilisée surtout pour la création d'objets avec un prototype explicite.

JS
let animal = {
  respirer() { return "respire"; },
  deplacer() { return "se déplace"; }
};

let chien = Object.create(animal);
chien.aboyer = () => "Wouf";

console.log(chien.aboyer());    // propre
console.log(chien.respirer());  // hérité
console.log(Object.getPrototypeOf(chien) === animal);  // true
Console
Wouf
respire
true
✏️ Ligne par ligne
Object.create(animal)crée un objet vide dont le prototype est animal.
chien.aboyer = ...ajoute une propriété propre à chien.
chien.respirer()pas sur chien → trouvé dans animal via prototype.

Avec un second argument pour initialiser des propriétés :

JS
let point = Object.create({}, {
  x: { value: 10, enumerable: true, writable: true },
  y: { value: 20, enumerable: true, writable: true }
});

console.log(point.x, point.y);  // 10 20
Console
10 20
📖 Mots à connaître
Object.create()méthode standard pour créer un objet avec un prototype choisi.
protole prototype à utiliser pour le nouvel objet — doit être un objet ou null.
descripteurobjet décrivant une propriété (value, writable, enumerable, configurable).
⚠️ Pièges fréquents
  • Passer null comme prototype (Object.create(null)) crée un objet sans prototype — il n'a même pas toString(). Utile pour des dictionnaires purs.
  • Object.create({}) crée un objet vide — penser à ajouter ensuite les propriétés nécessaires, sinon l'objet est inutilisable.
💡 Astuce

Rappel : voir la fiche 145 sur Object.getPrototypeOf() et la fiche 147 sur l'héritage prototypal — méthode historique avant les classes.

JS · Fiche Originale

Fiche 147 — Heritage prototypal
💡 En clair

L'héritage prototypal est le mécanisme original de JavaScript pour qu'un objet hérite d'un autre — avant l'arrivée des classes (ES6). On crée un objet parent, puis on en dérive des enfants via Object.create(). Les classes modernes ne sont qu'une syntaxe plus claire par-dessus ce mécanisme.

JS
// 1) Objet "parent"
let animal = {
  init(nom) { this.nom = nom; return this; },
  respirer() { return this.nom + " respire"; }
};

// 2) Objet "enfant" qui hérite
let chien = Object.create(animal);
chien.aboyer = function() { return this.nom + " dit Wouf"; };

// 3) Utilisation
let rex = Object.create(chien).init("Rex");
console.log(rex.respirer());
console.log(rex.aboyer());
Console
Rex respire
Rex dit Wouf
✏️ Ligne par ligne
Object.create(animal)chien hérite d'animal — pas besoin de classe.
init("Rex")méthode d'initialisation — remplace le constructor.
rex.respirer()méthode héritée via la chaîne des prototypes.

Aujourd'hui, on préfère les classes — équivalentes en interne :

JS
// Classe moderne — équivalent
class Animal {
  constructor(nom) { this.nom = nom; }
  respirer() { return this.nom + " respire"; }
}
class Chien extends Animal {
  aboyer() { return this.nom + " dit Wouf"; }
}

let rex = new Chien("Rex");
console.log(rex.respirer());
Console
Rex respire
📖 Mots à connaître
héritage prototypalmécanisme historique : objets qui héritent d'objets via prototype.
Object.create()méthode clé pour créer un objet héritant d'un autre — voir fiche 146.
sucre syntaxiqueles classes sont une syntaxe plus claire au-dessus des prototypes.
⚠️ Pièges fréquents
  • L'approche prototypale pure est moins lisible que les classes pour les hiérarchies complexes — réserver aux cas simples ou pour comprendre le moteur de JS.
  • Sans super en prototypal, l'appel à la méthode parente se fait via Animal.prototype.respirer.call(this) — verbeux.
💡 Astuce

Rappel : voir la fiche 146 sur Object.create() et la fiche 153 sur classe vs prototype pour comprendre l'équivalence.

JS · Fiche Originale

Fiche 148 — prototype
💡 En clair

La propriété prototype existe sur les fonctions constructeur et les classes : c'est l'objet qui deviendra le prototype des instances créées avec new. Toute méthode déclarée dans une classe est en réalité ajoutée à Classe.prototype.

JS
class Personne {
  saluer() { return "Bonjour"; }
}

console.log(typeof Personne.prototype.saluer);  // "function"
console.log(Personne.prototype.constructor === Personne);  // true

let p = new Personne();
console.log(Object.getPrototypeOf(p) === Personne.prototype);  // true
Console
function
true
true
✏️ Ligne par ligne
Personne.prototype.saluertoutes les méthodes déclarées dans la classe vivent ici.
Personne.prototype.constructorrétro-référence vers la classe elle-même.
Object.getPrototypeOf(p) === Personne.prototypele prototype de p est bien Personne.prototype.

Ajouter une méthode après coup via prototype :

JS
class Personne { constructor(nom) { this.nom = nom; } }

// Ajout d'une méthode à toutes les instances existantes
Personne.prototype.saluer = function() {
  return "Bonjour, je suis " + this.nom;
};

let p = new Personne("Awa");
console.log(p.saluer());  // OK, même si la méthode a été ajoutée après
Console
Bonjour, je suis Awa
📖 Mots à connaître
prototype (propriété)Classe.prototype — l'objet partagé par toutes les instances.
constructorrétro-référence de prototype vers la classe.
monkey patchingajouter des méthodes à un prototype existant — à utiliser avec prudence.
⚠️ Pièges fréquents
  • Modifier le prototype d'une classe après coup (monkey patching) peut casser le code existant — à éviter sauf cas précis (polyfills).
  • Ne pas confondre Classe.prototype (prototype des instances) avec Object.getPrototypeOf(Classe) (prototype de la classe elle-même).
💡 Astuce

Rappel : voir la fiche 143 sur le prototype d'un objet et la fiche 150 sur la différence prototype vs __proto__.

JS · Fiche Originale

Fiche 149 — Le lien prototype
💡 En clair

Le lien prototype est la relation cachée qui connecte chaque objet à son prototype. Quand on cherche une propriété, JS suit ce lien jusqu'à trouver la propriété ou atteindre la fin de la chaîne. Comprendre ce lien permet de déboguer l'héritage en JavaScript.

JS
class Animal {
  constructor(nom) { this.nom = nom; }
  respirer() { return this.nom + " respire"; }
}

let rex = new Animal("Rex");

// rex → Animal.prototype → Object.prototype → null
console.log(rex.nom);            // trouvé sur rex directement
console.log(rex.respirer());     // trouvé sur Animal.prototype
console.log(rex.toString());     // trouvé sur Object.prototype
Console
Rex
Rex respire
[object Object]
✏️ Ligne par ligne
rex.nompropriété propre à l'instance — trouvée immédiatement.
rex.respirer()pas sur rex → suit le lien vers Animal.prototype.
rex.toString()pas sur rex ni Animal → suit le lien vers Object.prototype.

Représentation visuelle de la chaîne :

JS
// Chaîne prototype de l'instance rex :
// rex (instance) ───► Animal.prototype ───► Object.prototype ───► null
//
// Sur rex : { nom: "Rex" }
// Sur Animal.prototype : { respirer(), constructor }
// Sur Object.prototype : { toString(), hasOwnProperty(), ... }
📖 Mots à connaître
lien prototyperelation cachée entre un objet et son prototype.
chaîne des prototypessuite de liens prototype parcourus lors d'une recherche.
propriété propredéfinie directement sur l'objet — pas héritée.
⚠️ Pièges fréquents
  • Le lien prototype est non énumérable — il n'apparaît pas dans Object.keys() ni dans un for...in.
  • Modifier ce lien après création (Object.setPrototypeOf) est très lent — préférer créer correctement l'objet dès le départ.
💡 Astuce

Rappel : voir la fiche 144 sur la chaîne des prototypes et la fiche 151 sur la recherche d'une propriété qui parcourt cette chaîne.

JS · Fiche Originale

Fiche 150 — prototype vs __proto__
💡 En clair

prototype et __proto__ sont deux notions souvent confondues. prototype est une propriété des fonctions/classes : c'est l'objet qui deviendra le prototype des futures instances. __proto__ est une propriété (obsolète) de chaque objet, pointant vers son prototype réel.

JS
class Personne { saluer() {} }

let p = new Personne();

console.log(Personne.prototype);              // { saluer, constructor }
console.log(p.__proto__);                     // IDEM — c'est le prototype de p
console.log(p.__proto__ === Personne.prototype);  // true
console.log(typeof p.prototype);             // "undefined" — p n'est pas une fonction
Console
{ saluer, constructor }
{ saluer, constructor }
true
undefined
✏️ Ligne par ligne
Personne.prototypeexiste seulement sur les fonctions/classes — prototype des instances.
p.__proto__existe sur tous les objets — pointe vers leur prototype réel.
p.__proto__ === Personne.prototypele prototype de p est bien Personne.prototype.
p.prototypeundefined — seules les fonctions ont une propriété prototype.

Règle simple à retenir :

JS
// Fonction/classe : possède .prototype (modèle)
// Instance : possède .__proto__ (lien vers son prototype)
//
// instance.__proto__ === Classe.prototype

// Approche moderne :
Object.getPrototypeOf(p) === Personne.prototype;  // true — préférer ceci
📖 Mots à connaître
prototypepropriété des fonctions/classes : prototype des futures instances.
__proto__propriété (obsolète) des objets : leur prototype réel.
Object.getPrototypeOf()méthode moderne pour lire le prototype — voir fiche 145.
⚠️ Pièges fréquents
  • __proto__ est officiellement déprécié — utiliser Object.getPrototypeOf() pour lire et Object.create() pour créer.
  • Écrire p.__proto__ = autreChose est très lent et casse les optimisations du moteur JS.
💡 Astuce

Rappel : voir la fiche 145 sur Object.getPrototypeOf() et la fiche 148 sur la propriété prototype.

JS · Fiche Originale

Fiche 151 — Recherche d une propriete
💡 En clair

Quand on accède à obj.propriete, JavaScript ne regarde pas seulement sur obj : il remonte la chaîne des prototypes jusqu'à trouver la propriété ou atteindre null. C'est ce qu'on appelle la délégation — un objet peut déléguer une méthode à son prototype.

JS
class Animal {
  constructor(nom) { this.nom = nom; }
  decrire() { return "Je suis " + this.nom; }
}

class Chien extends Animal {}

let rex = new Chien("Rex");

// rex n'a PAS decrire directement
console.log(rex.hasOwnProperty("decrire"));  // false

// Mais on peut l'appeler — trouvé via prototype
console.log(rex.decrire());  // "Je suis Rex"
Console
false
Je suis Rex
✏️ Ligne par ligne
rex.hasOwnProperty("decrire")faux : decrire n'est PAS sur rex lui-même.
rex.decrire()pourtant fonctionne — trouvé sur Animal.prototype via prototype.
Chien.prototypevide — pas de decrire. JS remonte à Animal.prototype.

Représentation du parcours :

JS
// rex (instance)
//   │  pas de "decrire" → continue
//   ▼
// Chien.prototype
//   │  pas de "decrire" → continue
//   ▼
// Animal.prototype
//   │  "decrire" trouvée ! ✓ → exécutée avec this = rex
//   ▼
// Object.prototype
//   │  pas de "decrire"
//   ▼
// null → fin de chaîne
📖 Mots à connaître
délégationun objet délègue l'accès à une propriété à son prototype.
propriété propredéfinie directement sur l'objet — trouvée immédiatement.
propriété héritéetrouvée plus loin dans la chaîne des prototypes.
⚠️ Pièges fréquents
  • La recherche s'arrête à la première propriété trouvée — une redéfinition masque les versions parentes.
  • Si la propriété n'existe nulle part, on obtient undefined — pas d'erreur. Pratique mais peut masquer des bugs.
💡 Astuce

Rappel : voir la fiche 144 sur la chaîne des prototypes et la fiche 152 sur hasOwnProperty() pour distinguer propriétés propres et héritées.

JS · Fiche Originale

Fiche 152 — hasOwnProperty
💡 En clair

hasOwnProperty(prop) est une méthode héritée d'Object.prototype qui renvoie true si la propriété est propre à l'objet (pas héritée via prototype). C'est l'outil pour distinguer ce qui appartient réellement à l'objet de ce qui vient par délégation.

JS
class Personne {
  constructor(nom) { this.nom = nom; }   // propre
  saluer() { return "Bonjour"; }          // sur prototype
}

let p = new Personne("Awa");

console.log(p.hasOwnProperty("nom"));     // true — propre
console.log(p.hasOwnProperty("saluer"));  // false — héritée
console.log(p.hasOwnProperty("age"));     // false — n'existe pas
Console
true
false
false
✏️ Ligne par ligne
p.hasOwnProperty("nom")vrai : nom est défini dans le constructor → propre.
p.hasOwnProperty("saluer")faux : saluer est sur Personne.prototype → héritée.
p.hasOwnProperty("age")faux : age n'existe pas du tout.

Cas d'usage — filtrer les propriétés propres dans un for...in :

JS
let user = { nom: "Awa", age: 25 };

for (let key in user) {
  if (user.hasOwnProperty(key)) {
    console.log(key + " = " + user[key]);
  }
}
Console
nom = Awa
age = 25
📖 Mots à connaître
hasOwnProperty()méthode qui teste si une propriété est propre à l'objet.
propre vs héritéepropre = sur l'objet ; héritée = via le prototype.
for...inboucle qui parcourt aussi les propriétés héritées — d'où le filtre.
⚠️ Pièges fréquents
  • Si un objet crée une propriété hasOwnProperty (par mégarde), elle masque la méthode héritée — utiliser Object.prototype.hasOwnProperty.call(obj, key) pour sécurité.
  • for...in parcourt les propriétés héritées aussi — d'où l'importance du filtre hasOwnProperty pour ne garder que les propres.
💡 Astuce

Alternative moderne : Object.keys(obj) ne renvoie que les propriétés propres énumérables — voir la fiche 118.

JS · Fiche Originale

Fiche 153 — Classe vs prototype
💡 En clair

Les classes (introduites en ES6) et l'héritage prototypal (historique) sont deux syntaxes pour le même mécanisme. Sous le capot, une classe génère des fonctions constructeur et un prototype. Choisir l'une ou l'autre est surtout une question de lisibilité.

JS
// SYNTAXE 1 — Classe moderne (ES6)
class Personne {
  constructor(nom) { this.nom = nom; }
  saluer() { return "Bonjour " + this.nom; }
}

// SYNTAXE 2 — Héritage prototypal (historique)
function PersonneP(nom) { this.nom = nom; }
PersonneP.prototype.saluer = function() {
  return "Bonjour " + this.nom;
};

// Résultat : instances identiques
let p1 = new Personne("Awa");
let p2 = new PersonneP("Awa");
console.log(p1.saluer());
console.log(p2.saluer());
Console
Bonjour Awa
Bonjour Awa
✏️ Ligne par ligne
class Personne { ... }syntaxe moderne — plus claire, plus lisible.
PersonneP.prototype.saluer = ...syntaxe historique — manuelle, verbeuse.
p1.saluer() === p2.saluer()même résultat : les deux approches aboutissent au même objet en mémoire.

Vérifions que les deux mécanismes sont équivalents :

JS
console.log(typeof Personne);          // "function" — une classe EST une fonction
console.log(Personne.prototype.constructor === Personne);  // true
// → Une classe n'est qu'une fonction spéciale avec un prototype attaché
Console
function
true
📖 Mots à connaître
classesyntaxe ES6 — sucre syntaxique par-dessus l'héritage prototypal.
prototypemécanisme réel d'héritage en JavaScript.
sucre syntaxiqueune syntaxe plus claire pour un mécanisme existant.
⚠️ Pièges fréquents
  • Les classes ne sont pas hissées — les utiliser avant leur déclaration provoque une ReferenceError (contrairement aux fonctions classiques).
  • Les classes ont aussi le mode strict implicite et une protection contre l'oubli de new — des avantages non négligeables par rapport à l'approche historique.
💡 Astuce

Rappel : voir la fiche 142 sur pourquoi les prototypes et la fiche 147 sur l'héritage prototypal pour comprendre ce que cachent les classes.

JS · Fiche Originale

Fiche 154 — Redefinition d une methode
💡 En clair

La redéfinition de méthode peut se faire en syntaxe classe OU en syntaxe prototypale. Le résultat est identique : on remplace une méthode héritée par une nouvelle version, propre à la sous-classe.

JS
// SYNTAXE 1 — Avec les classes (moderne)
class Animal {
  crier() { return "..."; }
}
class Chien extends Animal {
  crier() { return "Wouf !"; }   // redéfinition
}

// SYNTAXE 2 — Avec les prototypes (historique)
function AnimalP() {}
AnimalP.prototype.crier = function() { return "..."; };

function ChienP() {}
ChienP.prototype = Object.create(AnimalP.prototype);  // héritage
ChienP.prototype.crier = function() { return "Wouf !"; };  // redéfinition

console.log(new Chien().crier());
console.log(new ChienP().crier());
Console
Wouf !
Wouf !
✏️ Ligne par ligne
crier() { return "Wouf !"; }redéfinition propre à Chien — masque celle d'Animal.
ChienP.prototype = Object.create(AnimalP.prototype)définit l'héritage en prototypal.
ChienP.prototype.crier = ...redéfinition en prototypal — sur le prototype enfant.

Appeler la méthode parente — comparaison des deux syntaxes :

JS
// En classe :
class Chien extends Animal {
  crier() { return super.crier() + " (Wouf)"; }
}

// En prototypal :
ChienP.prototype.crier = function() {
  return AnimalP.prototype.crier.call(this) + " (Wouf)";
};
// → Beaucoup plus verbeux en prototypal — d'où l'intérêt des classes
📖 Mots à connaître
redéfinitionremplacer une méthode héritée par sa propre version.
super.methode()syntaxe moderne pour appeler la méthode parente.
Parent.prototype.method.call(this)syntaxe historique équivalente — verbeuse.
⚠️ Pièges fréquents
  • En prototypal, oublier .call(this) fait perdre la bonne valeur de this — bug sournois.
  • Redéfinir une méthode n'affecte pas les instances déjà créées — sauf si on redéfinit sur le prototype (auquel cas toutes les instances voient le changement).
💡 Astuce

Rappel : voir la fiche 137 sur la redéfinition en classes et la fiche 153 sur classe vs prototype pour l'équivalence.

13
Chapitre 138 fiches

Collections et iterateurs

Map, Set et protocole d iteration

JS · Fiche Originale

Fiche 155 — Utiliser un generateur
💡 En clair

Un générateur est une fonction qu'on peut mettre en pause et reprendre avec yield. Chaque appel à next() produit une nouvelle valeur, à la demande. Pratique pour produire des données sans tout calculer d'avance.

JS
// Créer un générateur
function* nombres() {
  yield 1;
  yield 2;
  yield 3;
}

// Obtenir les valeurs une par une
const gen = nombres();
console.log(gen.next());
console.log(gen.next());
console.log(gen.next());
Console
{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: false }
✏️ Ligne par ligne
function* nombres() { ... }déclare un générateur avec function*.
yield 1;produit 1 puis met la fonction en pause.
gen.next();reprend jusqu'au prochain yield.
done: false;il reste des valeurs à produire.
📖 Mots à connaître
function*déclare un générateur.
yieldproduit une valeur et met en pause.
next()reprend l'exécution jusqu'au prochain yield.
💡 Astuce

On peut parcourir un générateur directement avec for...of : for (let v of nombres()) console.log(v);. Voir la fiche 163c pour plus de détails.

JS · Fiche Originale

Fiche 156 — Map
💡 En clair

Une Map est une collection de paires clé/valeur comme un objet, mais avec des super-pouvoirs : n'importe quel type peut servir de clé (objet, fonction, primitive), elle conserve l'ordre d'insertion, et on connaît sa taille via .size.

JS
let ages = new Map();

// Ajouter des entrées
ages.set("Awa", 25);
ages.set("John", 30);
ages.set("Maria", 28);

// Lire
console.log(ages.get("Awa"));   // 25

// Taille
console.log(ages.size);         // 3

// Vérifier existence
console.log(ages.has("John"));  // true
Console
25
3
true
✏️ Ligne par ligne
ages.set("Awa", 25)ajoute ou met à jour une entrée.
ages.get("Awa")récupère la valeur associée à la clé.
ages.sizerenvoie le nombre d'entrées — pas besoin de Object.keys().length.
ages.has("John")vérifie si la clé existe.

On peut utiliser des objets comme clés (impossible avec un objet normal) :

JS
let user1 = { nom: "Awa" };
let user2 = { nom: "John" };

let scores = new Map();
scores.set(user1, 100);
scores.set(user2, 85);

console.log(scores.get(user1));  // 100
console.log(scores.size);        // 2
Console
100
2
📖 Mots à connaître
Mapcollection clé/valeur avec clés de n'importe quel type.
set(clé, val)ajoute ou met à jour une entrée.
get(clé)récupère la valeur associée à une clé.
sizepropriété qui donne le nombre d'entrées.
⚠️ Pièges fréquents
  • ages["Awa"] ne marche pas comme pour un objet — il faut utiliser ages.get("Awa").
  • Une Map se parcourt avec for...of ou .forEach, pas avec for...in qui est pour les objets.
💡 Astuce

Rappel : voir la fiche 157 sur Map vs objet et la fiche 161 sur les itérables — une Map est itérable.

JS · Fiche Originale

Fiche 157 — Map vs objet
💡 En clair

Map et objet sont tous les deux des collections clé/valeur, mais ils ont des forces différentes. La Map accepte n'importe quel type de clé et préserve l'ordre ; l'objet est limité aux clés de type chaîne/Symbol mais sa syntaxe littérale est plus concise.

JS
// Objet — clés limitées à string/Symbol
let obj = {};
let key = {};
obj[key] = "test";        // ⚠️ convertit key en "[object Object]"
console.log(Object.keys(obj));  // [ '[object Object]' ]

// Map — clés de n'importe quel type
let map = new Map();
map.set(key, "test");     // ✅ key reste un objet
console.log(map.get(key));  // "test"
console.log(map.size);     // 1
Console
[ '[object Object]' ]
test
1
✏️ Ligne par ligne
obj[key] = "test"convertit key en chaîne — toutes les clés objets deviennent "[object Object]".
map.set(key, "test")conserve key comme clé réelle — pas de conversion.
map.sizetaille directe — pas besoin de Object.keys().length.

Comparaison des opérations courantes :

JS
// OPÉRATION        OBJET                    MAP
// Ajouter          obj.k = v                map.set(k, v)
// Lire             obj.k                    map.get(k)
// Supprimer        delete obj.k            map.delete(k)
// Taille          Object.keys(obj).length map.size
// Vérifier         "k" in obj              map.has(k)
// Vider            obj = {}                map.clear()

// Parcourir        for (let k in obj)      for (let [k,v] of map)
📖 Mots à connaître
Mapcollection clé/valeur — clés de n'importe quel type, ordre préservé.
objetcollection clé/valeur — clés string/Symbol seulement.
itération ordonnéeMap préserve l'ordre d'insertion — objet non garanti.
⚠️ Pièges fréquents
  • Pour les données liées à un objet (ex. nombre de visites par utilisateur), utiliser une Map : avec un objet, deux clés key différentes collideraient en "[object Object]".
  • delete obj.k supprime mais ne renvoie pas la taille directement — plus lent et moins pratique que map.delete(k).
💡 Astuce

Choix : pour une simple collection de propriétés nommées → objet (syntaxe littérale). Pour des données dynamiques avec clés complexes → Map.

JS · Fiche Originale

Fiche 158 — WeakMap
💡 En clair

Une WeakMap est comme une Map, mais avec une contrainte : les clés doivent être des objets. L'avantage majeur est que les entrées ne bloquent pas le garbage collector : si l'objet-clé n'est plus référencé ailleurs, l'entrée disparaît automatiquement.

JS
let cache = new WeakMap();

function calculerLourd(user) {
  if (cache.has(user)) {
    console.log("cache hit");
    return cache.get(user);
  }
  const resultat = user.nom + " calculé";
  cache.set(user, resultat);
  return resultat;
}

let u = { nom: "Awa" };
console.log(calculerLourd(u));
console.log(calculerLourd(u));  // cache hit

u = null;  // l'objet n'est plus référencé → l'entrée sera supprimée par le GC
Console
Awa calculé
cache hit
Awa calculé
✏️ Ligne par ligne
cache.set(user, resultat)associe le résultat à l'objet user — pas à une chaîne.
cache.has(user)vérifie si on a déjà calculé pour cet objet précis.
u = nullquand plus personne ne référence u, le GC libère l'entrée cache correspondante.

Différences clés avec Map :

JS
// WeakMap vs Map
// ✓ Clés : objets uniquement (pas de primitives)
// ✓ Pas d'itération : pas de .keys(), .values(), .entries()
// ✓ Pas de .size
// ✓ Garbage-friendly : les clés faibles ne bloquent pas le GC
// → Idéal pour cacher des données liées à des objets éphémères
📖 Mots à connaître
WeakMapMap dont les clés sont des objets — non énumérable, pas de size.
référence faiblele GC peut libérer l'objet-clé sans prévenir la WeakMap.
cacheusage typique : mémoriser un calcul coûteux lié à un objet.
⚠️ Pièges fréquents
  • Pas de .size ni d'itération sur WeakMap — la spécification ne le permet pas car la présence d'une entrée dépend du GC.
  • Les clés doivent être des objets — weakMap.set("clé", val) provoque une TypeError.
💡 Astuce

Cas d'usage : mémoriser des métadonnées (cache, état interne) liées à un objet sans empêcher sa libération mémoire.

JS · Fiche Originale

Fiche 159 — WeakSet
💡 En clair

Un WeakSet est à Set ce que WeakMap est à Map : une collection d'objets uniques, sans bloquer le garbage collector. Pratique pour marquer des objets comme "déjà vus" ou "actifs" sans fuite de mémoire.

JS
let visites = new WeakSet();

function marquerVu(user) {
  if (visites.has(user)) {
    console.log("déjà vu");
    return;
  }
  visites.add(user);
  console.log("première visite");
}

let u1 = { nom: "Awa" };
let u2 = { nom: "John" };

marquerVu(u1);  // première visite
marquerVu(u1);  // déjà vu
marquerVu(u2);  // première visite
Console
première visite
déjà vu
première visite
✏️ Ligne par ligne
visites.add(user)ajoute l'objet au WeakSet.
visites.has(user)vérifie si l'objet a déjà été ajouté.
u1 = nullquand plus personne ne référence u1, le GC peut libérer l'entrée.

Différences avec Set :

JS
// WeakSet vs Set
// ✓ Valeurs : objets uniquement (pas de primitives)
// ✓ Pas d'itération : pas de .values(), .forEach()
// ✓ Pas de .size
// ✓ Garbage-friendly : les valeurs faibles ne bloquent pas le GC
// → Idéal pour "tagger" des objets sans fuite de mémoire
📖 Mots à connaître
WeakSetSet d'objets uniques — non itérable, sans size, garbage-friendly.
marquageusage typique : tagger des objets (déjà vus, actifs, validés).
GC-friendlyle garbage collector peut libérer les objets même s'ils sont dans le WeakSet.
⚠️ Pièges fréquents
  • Pas de .size ni d'itération — la spécification ne le permet pas.
  • Les valeurs doivent être des objets — weakSet.add(5) provoque une TypeError.
💡 Astuce

Cas d'usage : marquer des éléments du DOM comme déjà traités, ou des objets comme actifs — sans fuite de mémoire.

JS · Fiche Originale

Fiche 160 — Set vs Map vs Array
💡 En clair

Set, Map et Array sont trois collections avec trois intentions différentes. Array = liste ordonnée avec doublons. Set = ensemble sans doublons. Map = dictionnaire clé/valeur. Choisir la bonne collection simplifie énormément le code.

JS
// ARRAY — liste ordonnée, doublons OK
const notes = [12, 15, 12, 18];
console.log(notes.length);     // 4

// SET — ensemble, sans doublons
const tags = new Set(["js", "css", "js", "html"]);
console.log(tags.size);         // 3 — "js" compté une fois

// MAP — dictionnaire clé/valeur
const ages = new Map([["Awa", 25], ["John", 30]]);
console.log(ages.get("Awa"));   // 25
Console
4
3
25
✏️ Ligne par ligne
[12, 15, 12, 18]Array : ordre préservé, doublons autorisés.
new Set(["js", "css", "js"])Set : doublons automatiquement éliminés.
new Map([["Awa", 25]])Map : association clé/valeur, clés uniques.

Cas concret — dédupliquer un tableau avec Set :

JS
const avecDoublons = [1, 2, 2, 3, 3, 3, 4];
const sansDoublons = [...new Set(avecDoublons)];
console.log(sansDoublons);  // [1, 2, 3, 4]
Console
[1, 2, 3, 4]
📖 Mots à connaître
Arrayliste ordonnée avec doublons — accès par indice.
Setensemble de valeurs uniques — pas d'indice.
Mapdictionnaire clé/valeur — clés uniques.
⚠️ Pièges fréquents
  • Set n'a pas d'accès par indice : set[0] renvoie undefined. Utiliser set.values() ou [...set][0].
  • Map ne se parcourt pas comme un objet avec for...in — utiliser for (let [k,v] of map).
💡 Astuce

Rappel : voir la fiche 156 sur Map, la fiche 155 sur Set, et le chapitre 09 sur les tableaux.

JS · Fiche Originale

Fiche 161 — Iterable
💡 En clair

Un itérable est un objet qu'on peut parcourir avec for...of. Pour être itérable, un objet doit implémenter la méthode Symbol.iterator qui renvoie un itérateur. Tableaux, chaînes, Map, Set sont des itérables — les objets normaux ne le sont pas.

JS
// Itérables natifs
const tableau = [1, 2, 3];
const texte = "ABC";
const map = new Map([["a", 1], ["b", 2]]);
const set = new Set([10, 20]);

for (let x of tableau) console.log(x);  // 1, 2, 3
for (let c of texte) console.log(c);    // A, B, C
for (let [k, v] of map) console.log(k, v);  // a 1, b 2
for (let x of set) console.log(x);     // 10, 20
Console
1
2
3
A
B
C
a 1
b 2
10
20
✏️ Ligne par ligne
for (let x of tableau)parcourt les valeurs — pas les indices.
for (let c of texte)parcourt les caractères de la chaîne.
for (let [k, v] of map)déstructuration : chaque entrée est une paire [clé, valeur].

Un objet normal n'est PAS itérable — il faut for...in :

JS
const obj = { a: 1, b: 2 };

for (let key of obj) {  // ❌ TypeError: obj is not iterable
  console.log(key);
}

// for...in parcourt les clés (pas les valeurs)
for (let key in obj) {
  console.log(key, obj[key]);  // a 1, b 2
}
Console
a 1
b 2
📖 Mots à connaître
itérableobjet qu'on peut parcourir avec for...of — implémente Symbol.iterator.
itérateurobjet avec une méthode next() qui renvoie les valeurs une par une.
Symbol.iteratorméthode cachée que tout itérable doit implémenter.
⚠️ Pièges fréquents
  • Ne pas confondre for...in (parcourt les clés, marche sur les objets) et for...of (parcourt les valeurs, marche sur les itérables).
  • Un objet littéral {} n'est pas itérable par défaut avec for...of — il faut utiliser Object.keys(), Object.values() ou Object.entries().
💡 Astuce

Rappel : voir la fiche 162 sur les itérateurs et la fiche 163a sur les générateurs — un moyen simple de créer des itérables.

JS · Fiche Originale

Fiche 162 — Iterator
💡 En clair

Un itérateur est un objet avec une méthode next() qui renvoie la valeur suivante à chaque appel. C'est le "curseur" qui parcourt une collection. Tout itérable (Array, Map, Set...) fournit un itérateur via sa méthode Symbol.iterator.

JS
const nombres = [10, 20, 30];
const it = nombres[Symbol.iterator]();  // crée un itérateur

console.log(it.next());  // { value: 10, done: false }
console.log(it.next());  // { value: 20, done: false }
console.log(it.next());  // { value: 30, done: false }
console.log(it.next());  // { value: undefined, done: true }
Console
{ value: 10, done: false }
{ value: 20, done: false }
{ value: 30, done: false }
{ value: undefined, done: true }
✏️ Ligne par ligne
nombres[Symbol.iterator]()crée un itérateur pour ce tableau.
it.next()renvoie un objet { value, done } à chaque appel.
done: trueindique la fin du parcours — plus de valeur à renvoyer.

C'est exactement ce que fait for...of en interne :

JS
// Équivalent manuel de for...of
const it = nombres[Symbol.iterator]();
let resultat;
while (!(resultat = it.next()).done) {
  console.log(resultat.value);
}
// → même sortie que for (let x of nombres)
Console
10
20
30
📖 Mots à connaître
itérateurobjet avec une méthode next() qui produit des valeurs une par une.
next()renvoie { value, done } — value est la valeur courante, done indique la fin.
Symbol.iteratorméthode d'un itérable qui crée un itérateur.
⚠️ Pièges fréquents
  • Un itérateur est éphémère : une fois arrivé à done: true, il faut en recréer un pour reparcourir la collection.
  • Partager un même itérateur entre plusieurs boucles provoque des bugs — chaque boucle doit créer son propre itérateur.
💡 Astuce

Rappel : voir la fiche 161 sur les itérables et la fiche 163a sur les générateurs — un moyen simple de créer des itérateurs personnalisés.

14
Chapitre 143 fiches

Generateurs

Produire des valeurs a la demande

JS · Fiche Originale

Fiche 163a — Generators
💡 En clair

Un générateur (generator) est une fonction spéciale qui peut être mise en pause puis reprise. Au lieu de tout calculer d'un coup, elle produit ses valeurs une par une via le mot-clé yield. Idéal pour les suites infinies, les flux, ou les calculs paresseux.

JS
function* compteJusqua(max) {
  let n = 1;
  while (n <= max) {
    yield n;       // produit n, met en pause
    n++;
  }
}

const gen = compteJusqua(3);
console.log(gen.next());  // { value: 1, done: false }
console.log(gen.next());  // { value: 2, done: false }
console.log(gen.next());  // { value: 3, done: false }
console.log(gen.next());  // { value: undefined, done: true }
Console
{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: false }
{ value: undefined, done: true }
✏️ Ligne par ligne
function* compteJusqua(max)syntaxe : function* déclare un générateur — voir fiche 163b.
yield n;produit une valeur et met en pause jusqu'au prochain next().
gen.next()reprend l'exécution jusqu'au yield suivant.
done: trueindique la fin du générateur.

Le générateur est aussi un itérable — donc compatible for...of :

JS
function* nombres() {
  yield 10;
  yield 20;
  yield 30;
}

for (let n of nombres()) {
  console.log(n);
}

// Conversion en tableau
console.log([...nombres()]);  // [10, 20, 30]
Console
10
20
30
[10, 20, 30]
📖 Mots à connaître
générateurfonction qui se met en pause et reprend via yield.
yieldmot-clé qui produit une valeur et met en pause l'exécution.
itérateurobjet renvoyé par un générateur — voir fiche 162.
⚠️ Pièges fréquents
  • Un générateur est éphémère : une fois done: true atteint, on ne peut plus le réutiliser — il faut en recréer un.
  • yield ne marche que dans une fonction déclarée function* — pas dans une fonction classique ou une arrow function.
💡 Astuce

Rappel : voir la fiche 162 sur les itérateurs et la fiche 163b sur function*.

JS · Fiche Originale

Fiche 163b — function*
💡 En clair

On déclare un générateur avec la syntaxe function* (l'étoile fait la différence). À l'intérieur, on utilise yield pour produire des valeurs. Appeler la fonction ne l'exécute pas immédiatement — elle renvoie un itérateur qu'on pilote via .next().

JS
function* idGenerator() {
  let id = 1;
  while (true) {     // boucle infinie autorisée !
    yield id;
    id++;
  }
}

const gen = idGenerator();
console.log(gen.next().value);  // 1
console.log(gen.next().value);  // 2
console.log(gen.next().value);  // 3
Console
1
2
3
✏️ Ligne par ligne
function* idGenerator()l'étoile * déclare un générateur.
while (true) { yield id; }boucle infinie — sans problème car yield met en pause.
gen.next().valuerenvoie uniquement la valeur produite.

On peut aussi envoyer des valeurs dans le générateur via next(valeur) :

JS
function* conversation() {
  const nom = yield "Comment tu t'appelles ?";
  return "Bonjour " + nom;
}

const gen = conversation();
console.log(gen.next().value);         // question
console.log(gen.next("Awa").value);    // "Bonjour Awa"
Console
Comment tu t'appelles ?
Bonjour Awa
📖 Mots à connaître
function*syntaxe de déclaration d'un générateur.
yieldproduit une valeur (et peut recevoir une valeur via next()).
next(valeur)reprend l'exécution et peut envoyer une valeur au yield.
⚠️ Pièges fréquents
  • Une arrow function ne peut pas être un générateur — la syntaxe () =>* n'existe pas. Utiliser function*.
  • return dans un générateur termine l'itération (la valeur est renvoyée par le dernier next, puis done: true).
💡 Astuce

Rappel : voir la fiche 163a sur le principe et la fiche 163c sur l'utilisation d'un générateur.

JS · Fiche Originale

Fiche 163c — Utiliser un generateur
💡 En clair

Pour utiliser un générateur, on l'appelle pour créer un itérateur, puis on consomme ses valeurs avec .next(), for...of, ou le spread .... Le générateur exécute son code au fur et à mesure — c'est ce qui le rend "paresseux" et économe en mémoire.

JS
function* prendMultiples(tableau, n) {
  for (let i = 0; i < tableau.length; i++) {
    yield tableau[i] * n;
  }
}

const valeurs = [1, 2, 3, 4, 5];

// 1) Avec for...of
for (let v of prendMultiples(valeurs, 10)) {
  console.log(v);
}

// 2) Avec le spread
const resultats = [...prendMultiples(valeurs, 100)];
console.log(resultats);
Console
10
20
30
40
50
[100, 200, 300, 400, 500]
✏️ Ligne par ligne
prendMultiples(valeurs, 10)crée un itérateur — ne calcule rien pour l'instant.
for (let v of ...)déclenche l'exécution pas à pas, yield par yield.
[...prendMultiples(valeurs, 100)]matérialise toutes les valeurs dans un tableau.

Cas avancé — générateur infini (impossible avec une fonction classique) :

JS
function* fibonacci() {
  let a = 0, b = 1;
  while (true) {
    yield a;
    [a, b] = [b, a + b];  // destructuration
  }
}

const fib = fibonacci();
for (let i = 0; i < 8; i++) {
  console.log(fib.next().value);
}
Console
0
1
1
2
3
5
8
13
📖 Mots à connaître
consommationutiliser un générateur via next, for...of, ou spread.
paresseuxle calcul n'est fait qu'au moment où la valeur est demandée.
générateur infinipossible grâce à yield — ne consomme de la mémoire qu'au fur et à mesure.
⚠️ Pièges fréquents
  • Une fois le générateur consommé (done: true), il est épuisé — il faut en recréer un pour reparcourir.
  • Convertir un générateur infini en tableau avec [...gen] provoque une boucle infinie — ne jamais le faire.
💡 Astuce

Rappel : voir la fiche 161 sur les itérables et la fiche 162 sur les itérateurs — un générateur produit un itérateur.

15
Chapitre 157 fiches

Gestion des erreurs

Detecter, signaler et traiter les problemes

JS · Fiche Originale

Fiche 165 — Le mot-cle try
💡 En clair

Le mot-clé try ouvre un bloc de code surveillé : si une erreur s'y produit, elle n'arrête pas le programme — elle est captée par le bloc catch associé. Indispensable pour gérer les erreurs potentielles (parse JSON, fetch, calcul...).

JS
try {
  // code risqué
  let data = JSON.parse('{"nom":"Awa"}');
  console.log(data.nom);
} catch (erreur) {
  console.log("Oups :", erreur.message);
}

console.log("Programme continué !");
Console
Awa
Programme continué !
✏️ Ligne par ligne
try { ... }ouvre le bloc surveillé — toute erreur est captée.
catch (erreur) { ... }reçoit l'erreur et permet de réagir — voir fiche 166.
console.log("Programme continué !")preuve que le programme n'a pas planté.

Sans try/catch — une erreur fait planter tout le script :

JS
// Sans try/catch
let data = JSON.parse('invalide');  // ❌ SyntaxError
console.log("cette ligne ne s'exécutera jamais");
Console
SyntaxError: Unexpected token i in JSON
📖 Mots à connaître
trymot-clé qui ouvre un bloc surveillé.
catchbloc exécuté si une erreur se produit dans le try — voir fiche 166.
finallybloc toujours exécuté, succès ou erreur — voir fiche 167.
⚠️ Pièges fréquents
  • Le bloc try doit toujours être suivi d'un catch, d'un finally, ou des deux — jamais seul.
  • Un try vide ou inutile (sans code risqué) masque les bugs — réserver aux cas réellement incertains.
💡 Astuce

Rappel : voir la fiche 166 sur catch, la fiche 167 sur finally, et la fiche 168 sur throw pour lever soi-même une erreur.

JS · Fiche Originale

Fiche 166 — Le bloc catch
💡 En clair

Le bloc catch (erreur) est exécuté si une erreur se produit dans le try. Il reçoit l'erreur en paramètre (objet avec message, name, stack) et permet de réagir proprement : afficher un message, logger, retenter, etc.

JS
try {
  let user = JSON.parse('{"nom":"Awa"');  // JSON cassé
  console.log(user.nom);
} catch (erreur) {
  console.log("Nom de l'erreur :", erreur.name);
  console.log("Message :", erreur.message);
}

console.log("Programme non interrompu");
Console
Nom de l'erreur : SyntaxError
Message: Expected ':' after property name in JSON
Programme non interrompu
✏️ Ligne par ligne
catch (erreur)reçoit l'objet erreur — son nom est libre, souvent "e" ou "err".
erreur.namele type de l'erreur : SyntaxError, TypeError, RangeError...
erreur.messagela description textuelle — voir fiche 169.
erreur.stackla pile d'appels (utile en debug).

On peut choisir d'ignorer l'erreur (ES2019 — paramètre optionnel) :

JS
try {
  localStorage.setItem("cle", "valeur");
} catch {  // pas de paramètre
  console.log("localStorage indisponible");
}
Console
localStorage indisponible
📖 Mots à connaître
catchbloc exécuté en cas d'erreur dans le try.
erreur.namele type de l'erreur (SyntaxError, TypeError...).
erreur.messagela description textuelle — voir fiche 169.
⚠️ Pièges fréquents
  • Capturer une erreur pour l'ignorer silencieusement est une très mauvaise pratique — toujours au moins logger.
  • En mode strict (recommandé), un catch sans paramètre était interdit avant ES2019 — désormais accepté.
💡 Astuce

Rappel : voir la fiche 165 sur try, la fiche 167 sur finally, et la fiche 169 sur les types d'erreurs.

JS · Fiche Originale

Fiche 167 — Le bloc finally
💡 En clair

Le bloc finally est exécuté quel que soit le résultat du try : succès, erreur captée, ou même return dans le try. Indispensable pour libérer des ressources (fermer un fichier, une connexion...).

JS
function chargerConfig() {
  console.log("Début");
  try {
    let data = JSON.parse('{"env":"prod"}');
    return data;
  } catch (e) {
    console.log("Erreur :", e.message);
    return null;
  } finally {
    console.log("finally exécuté");  // toujours, même après return !
  }
}

console.log(chargerConfig());
Console
Début
finally exécuté
{ env: 'prod' }
✏️ Ligne par ligne
try { return data; }le return dans le try ne saute pas le finally.
finally { ... }exécuté après le return, avant que la fonction ne rende la main.
console.log(chargerConfig())affiche "finally exécuté" AVANT le résultat retourné.

Cas d'usage typique — fermer une ressource :

JS
let fichier;
try {
  fichier = ouvrirFichier("data.txt");
  let contenu = fichier.lire();
  console.log(contenu);
} catch (e) {
  console.log("Erreur de lecture :", e.message);
} finally {
  if (fichier) fichier.fermer();  // TOUJOURS fermer
}
📖 Mots à connaître
finallybloc exécuté systématiquement — succès, erreur, ou return.
libération de ressourceusage typique : fermer fichier, connexion, socket...
try/catch/finallyle trio complet de gestion d'erreurs.
⚠️ Pièges fréquents
  • Mettre un return dans le finally écrase celui du try — source de bugs subtils, à éviter.
  • finally s'exécute même si on lance une nouvelle erreur dans le catch — à garder en tête pour les enchaînements complexes.
💡 Astuce

Rappel : voir la fiche 165 sur try, la fiche 166 sur catch, et la fiche 168 sur throw pour lever soi-même une erreur.

JS · Fiche Originale

Fiche 168 — Le mot-cle throw
💡 En clair

Le mot-clé throw permet de lever une erreur soi-même. On peut lever n'importe quelle valeur, mais en pratique on lève un objet Error (ou une sous-classe) pour profiter de .name, .message, .stack. L'erreur remonte jusqu'à être captée par un catch.

JS
function verifierAge(age) {
  if (typeof age !== "number") {
    throw new TypeError("age doit être un nombre");
  }
  if (age < 0) {
    throw new RangeError("age ne peut pas être négatif");
  }
  return age >= 18 ? "majeur" : "mineur";
}

try {
  console.log(verifierAge(25));
  console.log(verifierAge(-5));
} catch (e) {
  console.log("Erreur :", e.name, "-", e.message);
}
Console
majeur
Erreur : RangeError - age ne peut pas être négatif
✏️ Ligne par ligne
throw new TypeError("...")lève une erreur typée — captée par un catch.
throw new RangeError("...")autre type — pour les erreurs de plage.
catch (e) { e.name, e.message }récupère les infos de l'erreur levée.

On peut lever n'importe quelle valeur (mais Error est recommandé) :

JS
// ⚠️ Possible mais déconseillé — pas de .message
throw "Une erreur";
throw 42;
throw { code: 500, detail: "..." };

// ✅ Recommandé — instance d'Error
throw new Error("Message clair");
throw new TypeError("Mauvais type");
throw new RangeError("Hors plage");
📖 Mots à connaître
throwmot-clé pour lever une erreur.
Errorobjet d'erreur standard — voir fiche 169 pour les sous-classes.
remontéel'erreur remonte la pile d'appels jusqu'au premier catch.
⚠️ Pièges fréquents
  • Lever une chaîne (throw "erreur") est possible mais perd le stack trace — toujours utiliser new Error().
  • Si aucune erreur n'est captée par un catch, le programme crash — toujours envelopper les zones risquées.
💡 Astuce

Rappel : voir la fiche 169 sur les types d'erreurs, la fiche 170 sur les erreurs personnalisées, et la fiche 171 sur la propagation.

JS · Fiche Originale

Fiche 169 — Les types d erreurs
💡 En clair

JavaScript fournit plusieurs types d'erreurs natifs, chacun correspondant à une catégorie de problème. Les connaître permet de lever (throw) et capturer (catch) les bonnes erreurs, et de réagir différemment selon la cause.

JS
// TypeError — mauvais type
try { null.foo(); } catch (e) { console.log(e.name); }

// RangeError — valeur hors plage
try { let a = new Array(-1); } catch (e) { console.log(e.name); }

// SyntaxError — code mal formé
try { eval("let = 5"); } catch (e) { console.log(e.name); }

// ReferenceError — variable inconnue
try { console.log(inconnue); } catch (e) { console.log(e.name); }
Console
TypeError
RangeError
SyntaxError
ReferenceError
✏️ Ligne par ligne
TypeErroropération impossible sur ce type — null.foo(), "a" * 2...
RangeErrorvaleur hors limites — tableau négatif, recursivité trop profonde.
SyntaxErrorcode mal formé — oubli de parenthèses, virgule en trop.
ReferenceErrorvariable non définie — faute de frappe, portée incorrecte.

Tableau récapitulatif des types natifs :

JS
// Error            — la base, type générique
// TypeError        — mauvais type ou opération impossible
// RangeError       — valeur hors plage
// SyntaxError      — code invalide (parse ou eval)
// ReferenceError   — variable inexistante
// URIError         — mauvaise utilisation de decodeURI/encodeURI
// EvalError        — usage incorrect de eval (rare)
📖 Mots à connaître
TypeErroropération impossible avec ce type.
RangeErrorvaleur numérique hors limite autorisée.
SyntaxErrorcode JavaScript invalide.
ReferenceErrorvariable ou fonction inconnue.
⚠️ Pièges fréquents
  • Toutes ces erreurs héritent d'Error — on peut donc les capturer génériquement via catch (e).
  • En Node.js, il existe aussi des erreurs spécifiques au système (ex. SystemError) qui ne sont pas dans ECMAScript.
💡 Astuce

Pour distinguer les types dans un catch : if (e instanceof TypeError) { ... } — voir la fiche 139 sur instanceof.

JS · Fiche Originale

Fiche 170 — Creer une erreur personnalisee
💡 En clair

On peut créer ses propres erreurs personnalisées en héritant d'Error. Cela permet d'ajouter des champs utiles (code, contexte) et de les capturer spécifiquement via instanceof. Indispensable pour une gestion d'erreurs métier propre.

JS
class ValidationError extends Error {
  constructor(champ, message) {
    super(message);
    this.name = "ValidationError";
    this.champ = champ;     // champ personnalisé
  }
}

function verifierEmail(email) {
  if (!email.includes("@")) {
    throw new ValidationError("email", "Email invalide : " + email);
  }
  return "OK";
}

try {
  verifierEmail("awa.mail.com");
} catch (e) {
  if (e instanceof ValidationError) {
    console.log(`Champ ${e.champ} : ${e.message}`);
  } else {
    console.log("Erreur inattendue :", e);
  }
}
Console
Champ email : Email invalide : awa.mail.com
✏️ Ligne par ligne
class ValidationError extends Errorsous-classe d'Error — voir fiche 135 sur extends.
super(message)appelle le constructor d'Error — obligatoire avant this. Voir fiche 136.
this.champ = champajoute un champ personnalisé pour le debug.
e instanceof ValidationErrorpermet de distinguer ce type d'erreur — voir fiche 139.

Cas pratique — plusieurs types d'erreurs métier :

JS
class NotFoundError extends Error { /* ... */ }
class UnauthorizedError extends Error { /* ... */ }
class PaymentError extends Error { /* ... */ }

try {
  // ... opérations métier
} catch (e) {
  if (e instanceof NotFoundError)    return res.status(404).send(e.message);
  if (e instanceof UnauthorizedError) return res.status(401).send(e.message);
  if (e instanceof PaymentError)     return res.status(402).send(e.message);
  return res.status(500).send("Erreur interne");
}
📖 Mots à connaître
erreur personnaliséesous-classe d'Error avec champs et comportements spécifiques.
extends Errorhérite de la classe Error — voir fiche 135.
instanceofopérateur pour distinguer les types d'erreurs — voir fiche 139.
⚠️ Pièges fréquents
  • Oublier super(message) dans le constructor provoque une ReferenceError — voir la fiche 136.
  • Ne pas mettre this.name peut fausser les logs — par défaut il vaut "Error", ce qui le rend indissociable d'une erreur générique.
💡 Astuce

Rappel : voir la fiche 135 sur extends, la fiche 139 sur instanceof, et la fiche 171 sur la propagation des erreurs.

JS · Fiche Originale

Fiche 171 — Propagation d une erreur
💡 En clair

La propagation d'une erreur (propagation) est le mécanisme par lequel une erreur non captée remonte la pile d'appels, de fonction en fonction, jusqu'à trouver un catch — ou jusqu'au niveau global où elle fait crasher le programme. Comprendre cette remontée est clé pour décider où gérer chaque erreur.

JS
function lireFichier() {
  throw new Error("Fichier introuvable");
}

function chargerConfig() {
  return lireFichier();  // ne catch pas → l'erreur remonte
}

function demarrerApp() {
  try {
    chargerConfig();
  } catch (e) {
    console.log("Capture au niveau app :", e.message);
  }
}

demarrerApp();
console.log("Programme non interrompu");
Console
Capture au niveau app : Fichier introuvable
Programme non interrompu
✏️ Ligne par ligne
throw new Error("...") dans lireFichierlève l'erreur.
return lireFichier() dans chargerConfigpas de catch → l'erreur remonte.
try { chargerConfig() } dans demarrerAppcapture l'erreur au niveau approprié.
console.log("...non interrompu")preuve que le catch a empêché le crash.

Si aucune fonction ne catch — crash du programme :

JS
function a() { throw new Error("boom"); }
function b() { a(); }
function c() { b(); }

c();  // ❌ Error non captée → crash
console.log("jamais atteint");
Console
Error: boom
at a ...
at b ...
at c ...
📖 Mots à connaître
propagationremontée d'une erreur dans la pile d'appels.
pile d'appelscall stack — suite de fonctions en cours d'exécution.
catch centralisécapturer l'erreur à un seul endroit stratégique.
⚠️ Pièges fréquents
  • Capturer une erreur trop tôt (à chaque niveau) empêche la gestion centralisée — préférable de laisser remonter jusqu'à un point stratégique.
  • Une erreur non captée dans un setTimeout ou un .then() ne remonte pas à l'appelant — il faut un catch dans le callback asynchrone.
💡 Astuce

Rappel : voir la fiche 165 sur try, la fiche 168 sur throw, et le chapitre 18 sur les Promesses — la propagation y est un peu différente.

16
Chapitre 166 fiches

JSON

Echanger et stocker des donnees

JS · Fiche Originale

Fiche 164 — JSON et tableaux
💡 En clair

JSON represente un tableau avec des crochets [ ], comme en JavaScript. Mais une fois serialise en JSON, ce n est plus un vrai tableau : c est une chaine de caracteres qu il faut reparser pour retrouver les methodes .map(), .filter(), etc.

Tableau JSON simple :

JSON
["HTML", "CSS", "JavaScript"]

Tableau d objets (la forme la plus courante quand un serveur renvoie une liste) :

JSON
[
  { "nom": "Awa", "age": 25 },
  { "nom": "Moussa", "age": 30 },
  { "nom": "Fatou", "age": 22 }
]
💻 En JavaScript

Une fois le JSON converti avec JSON.parse(), on accede aux elements comme dans n importe quel tableau :

JS
let json = '[{"nom":"Awa"},{"nom":"Moussa"}]';
let data = JSON.parse(json);

console.log(data[0].nom);  // "Awa"
console.log(data[1].nom);  // "Moussa"
console.log(data.length);   // 2
💡 Exemple concret

Quand tu ouvres une appli de musique, le serveur renvoie souvent une liste de chansons sous forme d un tableau JSON d objets. L application lit le tableau et affiche chaque chanson dans la liste.

JS · Fiche Originale

Fiche 172 — Qu’est-ce que JSON ?
💡 En clair

JSON signifie JavaScript Object Notation. C est un format de texte qui sert a stocker et echanger des donnees entre programmes, sites web et serveurs.

JSON est independant du langage : un programme Python, Java ou PHP peut le lire tout comme JavaScript. C est pourquoi il est devenu le standard d echange sur le web.

JSON
{
  "nom": "Awa",
  "age": 25,
  "ville": "Dakar",
  "estEtudiant": true,
  "competences": ["HTML", "CSS", "JavaScript"]
}
📖 Les 6 types JSON
{ }objet (ensemble de paires clé-valeur)
[ ]tableau (liste ordonnée)
" "texte (chaîne de caractères)
25nombre (entier ou décimal)
true / falsebooléen (vrai / faux)
nullvaleur vide
💡 Pourquoi JSON est partout

JSON est leger et lisible par un humain comme par une machine.

Il est universel : tous les langages le lisent via leur bibliotheque dediee.

Il est le standard du web : les reponses d API sont presque toujours en JSON.

🌐 Exemple concret

Quand tu ouvres une appli meteo, ton telephone envoie une demande a un serveur, qui repond en JSON :

JSON
{
  "ville": "Dakar",
  "temperature": 28,
  "condition": "Ensoleille"
}

L application lit ce JSON, extrait temperature, ville et condition, puis les affiche a l ecran. JSON sert de messager entre le serveur et ton telephone.

JS · Fiche Originale

Fiche 173 — Objet JavaScript vs JSON
⚠ A ne pas confondre

Un objet JavaScript vit en memoire dans ton programme : on peut appeler ses methodes, le modifier, utiliser undefined ou des fonctions.

Le JSON, lui, est une chaine de caracteres : un simple texte qu on peut envoyer, stocker ou recevoir. On ne peut pas appeler une methode sur du JSON tant qu il n est pas parse en objet.

📖 Differences en detail
NatureObjet JS = structure en mémoire · JSON = texte (string)
ClésObjet JS : avec ou sans guillemets · JSON : toujours entre "
GuillemetsObjet JS : ' ' ou " " · JSON : uniquement " "
FonctionsObjet JS : ✅ autorisées · JSON : ❌ interdites
CommentairesObjet JS : ✅ autorisés · JSON : ❌ interdits
undefinedObjet JS : ✅ autorisé · JSON : ❌ interdit
Virgule finaleObjet JS : ✅ tolérée · JSON : ❌ interdite

Exemple d objet JavaScript (vivant, flexible) :

JS
let user = {
  nom: "Awa",          // cl&eacute; sans guillemets
  age: 25,
  direBonjour: function() {
    console.log("Salut");
  }
};

Le même en JSON (texte figé, strict) :

JSON
{
  "nom": "Awa",
  "age": 25
}
💡 Le lien avec les fiches suivantes

Quand ton programme manipule des donnees, il utilise un objet JavaScript.

Pour envoyer ces donnees a un serveur, il doit les transformer en texte JSON avec JSON.stringify().

Quand il recupere du JSON d un serveur, il doit le retransformer en objet avec JSON.parse().

C est exactement le rôle des deux methodes des fiches suivantes.

JS · Fiche Originale

Fiche 174 — JSON.stringify()
💡 Action

JSON.stringify(valeur) transforme une valeur JavaScript en texte JSON. C est ce qu on utilise avant d envoyer des donnees a un serveur, de les sauvegarder dans localStorage ou de les ecrire dans un fichier.

✏ Syntaxe generale

JSON.stringify(valeur) — forme minimale.

JSON.stringify(valeur, null, 2) — avec indentation de 2 espaces pour un rendu lisible.

Le 2e parametre (null ici) permet de filtrer les cles ; on l utilise rarement.

JS
JSON.stringify(valeur)
JSON.stringify(valeur, null, 2)
JSON.stringify(valeur, replacer, espace)

Exemple simple :

JS
let user = { nom: "Awa", age: 25 };

let json = JSON.stringify(user);
console.log(json);
// '{"nom":"Awa","age":25}'

Avec indentation lisible :

JS
let json = JSON.stringify(user, null, 2);
console.log(json);
JSON
{
  "nom": "Awa",
  "age": 25
}
⚠ Valeurs ignorees

Certaines valeurs n existent pas en JSON. JSON.stringify() les ignore silencieusement (pas d erreur, mais la valeur disparait) :

JS
JSON.stringify({ a: undefined });    // '{}'
JSON.stringify({ a: function(){} }); // '{}'
JSON.stringify({ a: Symbol() });      // '{}'
JSON.stringify([1, 2, 3]);           // '[1,2,3]'
💡 Exemple concret

Quand tu remplis un formulaire et cliques sur Envoyer, le navigateur transforme souvent les donnees en JSON avec JSON.stringify() avant de les envoyer au serveur via fetch().

JS · Fiche Originale

Fiche 175 — JSON et tableaux
💡 Cycle

Pour retrouver un tableau (ou un objet) manipulable apres l avoir converti en texte JSON, il faut toujours faire les deux etapes :

1. JSON.stringify() transforme le tableau en chaine JSON (pour l envoyer ou le stocker).

2. JSON.parse() reconstruit une vraie valeur JavaScript a partir du texte recu.

JS
// 1. On a un tableau vivant
let fruits = ["pomme", "banane", "cerise"];

// 2. On le convertit en texte pour l envoyer / stocker
let texteJSON = JSON.stringify(fruits);
// '["pomme","banane","cerise"]'

// 3. Cote reception, on retransforme en tableau
let recus = JSON.parse(texteJSON);
console.log(recus[0]); // "pomme"
console.log(recus.length); // 3
⚠ Sans parse, impossible d utiliser les donnees

texteJSON[0] retourne "[" (le premier caractere de la chaine), pas "pomme".

Tant que tu n as pas appele JSON.parse(), ta valeur reste une chaine de caracteres et non un tableau.

💡 Cas typique

Dans le navigateur, tu peux stocker un tableau en localStorage avec JSON.stringify(), puis le recuperer plus tard avec JSON.parse(). localStorage ne sait stocker que des chaines.

JS · Fiche Originale

Fiche 177 — Erreurs de parsing JSON
⚠ Piege

JSON est strict : une virgule, un guillemet ou un mot de travers — et JSON.parse() lance une erreur qui peut faire planter tout le programme.

Les erreurs classiques :

JS
// &#10060; Cl&eacute; sans guillemets
JSON.parse('{nom: "Awa"}')

// &#10060; Guillemets simples
JSON.parse("{'nom': 'Awa'}")

// &#10060; Virgule en trop
JSON.parse('{"nom":"Awa",}')

// &#10060; Commentaire
JSON.parse('{"nom":"Awa"} // test')

// &#10060; undefined interdit
JSON.parse('{"nom": undefined}')

Message d erreur typique :

Erreur
SyntaxError: Unexpected token n in JSON at position 1

Ce message indique qu a la position 1, le parseur a trouvé quelque chose d inattendu (ici, la clé nom sans guillemets).

✅ Bonne pratique : try / catch

Pour eviter que le programme plante, on entoure toujours JSON.parse() d un try...catch quand la source n est pas 100% fiable (API, fichier, input utilisateur...) :

JS
try {
  let data = JSON.parse(texte);
  console.log(data);
} catch (erreur) {
  console.log("JSON invalide :", erreur.message);
}
💡 Exemple concret

Si une API renvoie une reponse vide ou mal formee (bug serveur, coupure reseau...), ton try/catch t evite un ecran blanc chez l utilisateur. Tu peux afficher un message d erreur propre a la place.

17
Chapitre 178 fiches

Asynchronisme

Callbacks, Promises et etats futurs

JS · Fiche Originale

Fiche 178 — Synchrone vs asynchrone
💡 En clair

En JavaScript, le code s execute ligne par ligne, de haut en bas. C est le comportement synchrone.

Mais certaines taches prennent du temps (attendre un serveur, un fichier, un minuteur...). Si on les attendait, tout le programme serait bloque. C est la qu intervient l asynchrone.

Synchrone — chaque ligne attend son tour :

JS
console.log("1");
console.log("2");
console.log("3");
Console
1
2
3

Asynchrone — certaines taches sont lancees en arriere-plan :

JS
console.log("1");
setTimeout(() => console.log("2"), 2000); // attend 2 secondes
console.log("3");
Console
1
3
2 ← apparait apres 2 secondes

Le 2 arrive en dernier, meme s il est ecrit avant le 3. Parce que setTimeout lance la tache en arriere-plan et rend la main tout de suite.

📖 Comparaison
ExecutionSynchrone : ligne par ligne · Asynchrone : en arriere-plan
Bloque le programmeSynchrone : ✅ oui · Asynchrone : ❌ non
OrdreSynchrone : previsible · Asynchrone : peut changer
ExempleSynchrone : console.log() · Asynchrone : setTimeout(), fetch()
🌐 Exemple concret

Imagine un restaurant :

Synchrone : le serveur prend une commande, attend qu elle soit cuisinee, la sert, puis prend la suivante. Les clients attendent longtemps.

Asynchrone : le serveur prend une commande, la transmet en cuisine, puis prend la suivante pendant que la premiere cuit. Tout le monde est servi plus vite.

JS · Fiche Originale

Fiche 179 — Pourquoi l’asynchrone ?
💡 En clair

JavaScript est mono-thread : il ne peut executer qu une seule chose a la fois. S il attendait chaque tache lente, la page web gelerait completement.

L asynchrone permet de ne pas bloquer le programme pendant les taches longues.

⚠ Le probleme sans asynchrone

Imagine que tu telecharges une image depuis un serveur. Si JavaScript attendait la reponse :

JS
let image = telechargerImage("photo.jpg"); // prend 3 secondes
console.log("Image affichee");

Pendant 3 secondes, rien d autre ne fonctionne : pas de clic, pas de scroll, pas d animation. La page est figee.

✅ La solution avec asynchrone

On lance la tache, et on continue :

JS
telechargerImage("photo.jpg", function(image) {
  console.log("Image affichee");
});
console.log("Le programme continue");
Console
Le programme continue
Image affichee ← apres 3 secondes

Le programme continue a tourner pendant que l image se telecharge.

📖 Taches typiquement asynchrones
ReseauRequetes HTTP (fetch, XMLHttpRequest)
FichiersLecture / ecriture (Node.js : fs.readFile)
MinuteriessetTimeout, setInterval
EvenementsClic, clavier, scroll
Bases de donneesRequetes SQL, NoSQL
🌐 Exemple concret

Quand tu ouvres YouTube :

1. La page s affiche immediatement (synchrone).

2. Les videos, commentaires, miniatures se chargent en arriere-plan (asynchrone).

3. Tu peux deja cliquer, scroller, chercher, meme si tout n est pas encore charge.

Sans asynchrone, tu devrais attendre que tout soit charge avant de pouvoir faire quoi que ce soit.

JS · Fiche Originale

Fiche 180 — setTimeout()
💡 Role

setTimeout() execute une fonction apres un certain delai (en millisecondes).

✏ Syntaxe generale

setTimeout(fonction, delai) — forme minimale.

setTimeout(fonction, delai, arg1, arg2, ...) — avec arguments passes a la fonction.

fonction : la fonction a executer.

delai : temps en millisecondes (1000 ms = 1 seconde).

JS
setTimeout(fonction, delai);
setTimeout(fonction, delai, arg1, arg2);

Exemple simple :

JS
setTimeout(() => {
  console.log("3 secondes plus tard");
}, 3000);

Resultat : le message apparait apres 3 secondes.

Avec arguments :

JS
function saluer(nom) {
  console.log(`Bonjour ${nom}`);
}

setTimeout(saluer, 2000, "Awa");
// Apres 2 secondes : "Bonjour Awa"

Avec un delai de zero :

JS
console.log("1");
setTimeout(() => console.log("2"), 0);
console.log("3");
Console
1
3
2
⚠ Delai zero ne signifie pas immediat

Meme avec 0, le 2 passe apres le 3. Car setTimeout place toujours la tache en file d attente, jamais immediatement.

🔄 Annuler un setTimeout

setTimeout retourne un identifiant qu on peut utiliser pour l annuler avec clearTimeout() :

JS
let id = setTimeout(() => console.log("Jamais execute"), 3000);
clearTimeout(id); // annule
🌐 Exemple concret — debounce de recherche

Sur un site de recherche, quand tu tapes dans la barre, le site attend 500 ms avant de lancer la requete au serveur. Si tu continues a taper, l ancien timer est annule et un nouveau demarre. Evite d envoyer une requete a chaque lettre tapee :

JS
let timer;

input.addEventListener("input", () => {
  clearTimeout(timer);
  timer = setTimeout(() => {
    rechercher(input.value);
  }, 500);
});

JS · Fiche Originale

Fiche 181 — Callback asynchrone
💡 En clair

Un callback asynchrone, c est une fonction qu on passe en argument a une autre fonction, et qui sera appelee quand la tache asynchrone sera terminee.

C est la base de l asynchrone en JavaScript.

✏ Syntaxe generale

fonctionAsync(callback) — la fonction recoit un callback qu elle appelera plus tard avec le resultat.

Le callback est souvent de la forme (erreur, resultat) — c est la convention Node.js.

JS
function tacheAsync(callback) {
  // ... travail asynchrone
  callback(resultat); // appel du callback quand c est fini
}

tacheAsync(function(resultat) {
  console.log(resultat);
});

Exemple simple :

JS
function chargerDonnees(callback) {
  setTimeout(() => {
    let donnees = "Voici les donnees";
    callback(donnees); // appele apres 2 secondes
  }, 2000);
}

chargerDonnees(function(resultat) {
  console.log(resultat); // "Voici les donnees"
});

La fonction anonyme passee a chargerDonnees est un callback asynchrone : elle ne s execute pas tout de suite, mais quand les donnees sont pretes.

✅ Avec gestion d erreur (style Node.js)

Souvent, le callback prend deux parametres : une erreur et un resultat :

JS
function chargerDonnees(callback) {
  setTimeout(() => {
    let erreur = null;
    let donnees = "Voici les donnees";
    callback(erreur, donnees);
  }, 2000);
}

chargerDonnees(function(erreur, resultat) {
  if (erreur) {
    console.log("Erreur :", erreur);
  } else {
    console.log(resultat);
  }
});
🌐 Exemple concret

Quand tu cliques sur Envoyer un formulaire :

1. Le navigateur envoie les donnees au serveur (asynchrone).

2. Quand la reponse arrive, un callback est appele.

3. Ce callback affiche Message envoye ou une erreur.

JS
envoyerFormulaire(donnees, function(erreur, reponse) {
  if (erreur) {
    afficherErreur(erreur);
  } else {
    afficherSucces(reponse);
  }
});

JS · Fiche Originale

Fiche 182 — Callback Hell
💡 En clair

Quand on enchaine plusieurs taches asynchrones avec des callbacks, on obtient une pyramide illisible appelee callback hell (enfer des callbacks).

⚠ Le probleme

Chaque etape depend de la precedente. Le code part vers la droite au lieu du haut vers le bas. C est difficile a lire, a debugger et a maintenir.

JS
chargerUtilisateur(1, function(user) {
  chargerPosts(user.id, function(posts) {
    chargerCommentaires(posts[0].id, function(commentaires) {
      chargerAuteur(commentaires[0].id, function(auteur) {
        console.log(auteur);
      });
    });
  });
});
📖 Pourquoi c est un probleme
IllisibleLa logique est noyee dans l imbrication
Difficile a modifierAjouter une etape au milieu casse tout
Gestion d erreur lourdeIl faut repeter if (erreur) a chaque niveau
Nomme« pyramide de la doom » (pyramid of doom)

Avec gestion d erreur, c est pire :

JS
chargerUtilisateur(1, function(err, user) {
  if (err) return gererErreur(err);
  chargerPosts(user.id, function(err, posts) {
    if (err) return gererErreur(err);
    chargerCommentaires(posts[0].id, function(err, commentaires) {
      if (err) return gererErreur(err);
      console.log(commentaires);
    });
  });
});

Le if (err) est repete a chaque niveau. Tres lourd.

✅ La solution : les Promesses

Les Promesses (Promise) ont ete creees pour resoudre ce probleme :

JS
chargerUtilisateur(1)
  .then(user => chargerPosts(user.id))
  .then(posts => chargerCommentaires(posts[0].id))
  .then(commentaires => console.log(commentaires))
  .catch(erreur => gererErreur(erreur));

Le code repart vers le bas, lisible, avec une seule gestion d erreur a la fin avec .catch().

🌐 Exemple concret

Imagine que tu doives :

1. Recuperer un utilisateur

2. Puis ses commandes

3. Puis les details du premier produit de la premiere commande

4. Puis l avis sur ce produit

Avec des callbacks imbriques, ca fait 4 niveaux. Avec des Promesses, ca reste plat et lisible.

JS · Fiche Originale

Fiche 183A — Promise
💡 En clair

Une Promise (promesse) est un objet qui represente une valeur qui n est pas encore disponible, mais qui le sera plus tard.

C est exactement comme une promesse dans la vie reelle : « Je te promets de te donner le resultat quand j aurai fini ».

⚠ Le probleme qu elle resout

Avant les Promesses, on gerait l asynchrone avec des callbacks imbriques (callback hell). Les Promesses permettent d ecrire l asynchrone de facon plus lisible, comme une chaine d etapes.

✏ Syntaxe generale

On cree une Promise avec new Promise(), en lui passant une fonction avec deux parametres : resolve et reject.

resolve : fonction a appeler quand tout se passe bien.

reject : fonction a appeler quand il y a une erreur.

JS
let promesse = new Promise((resolve, reject) => {
  // travail asynchrone
});

Exemple simple :

JS
let promesse = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("Donnees recues");
  }, 2000);
});

promesse.then(resultat => console.log(resultat));
// Apres 2 secondes : "Donnees recues"

La promesse dit : « Je te donnerai un resultat dans 2 secondes ».

🧮 Image mentale

Imagine que tu commandes un plat au restaurant :

Le serveur te donne un beeper (la promesse).

Tu ne sais pas encore si le plat sera pret (resolu) ou s il y aura un probleme (rejete).

Quand le beeper sonne, tu sais que c est pret (.then()) ou qu il y a eu un souci (.catch()).

🌐 Exemple concret

Quand tu envoies une requete a un serveur avec fetch(), ca retourne une Promise :

JS
let promesse = fetch("https://api.exemple.com/user");

Cette promesse dit : « Je te donnerai la reponse du serveur quand elle arrivera ». En attendant, le programme continue.

JS · Fiche Originale

Fiche 183B — Etats d une Promise
💡 En clair

Une Promise a 3 etats possibles, et elle ne peut en changer qu une seule fois.

📖 Les 3 etats
En attentePas encore de resultat — pending
ResolueSucces, valeur disponible — fulfilled
RejeteeEchec, erreur disponible — rejected

Cycle de vie :

Cycle
         +-------------+
         |   pending   |
         +------+------+
                |
        +-------+-------+
        |               |
        v               v
   +---------+     +----------+
   |fulfilled|     | rejected |
   +---------+     +----------+

Une fois qu une promesse est resolue ou rejetee, elle est figee : elle ne peut plus changer d etat.

Exemple — promesse resolue :

JS
let p = new Promise((resolve, reject) => {
  resolve("Succes");
});

p.then(valeur => console.log(valeur)); // "Succes"

Exemple — promesse rejetee :

JS
let p = new Promise((resolve, reject) => {
  reject("Erreur");
});

p.catch(erreur => console.log(erreur)); // "Erreur"

Exemple — promesse en attente :

JS
let p = new Promise((resolve, reject) => {
  setTimeout(() => resolve("Fini"), 3000);
});

console.log(p); // Promise { <pending> }
// apres 3 secondes -> Promise { "Fini" }
🌐 Exemple concret

Quand tu commandes un colis en ligne :

pending : le colis est en cours de livraison

fulfilled : le colis est arrive ✅

rejected : le colis a ete perdu ❌

Une fois livre (ou perdu), l etat ne change plus.

JS · Fiche Originale

Fiche 184 — Creer une Promise
💡 En clair

On cree une Promise avec le mot-cle new Promise(), en lui passant une fonction avec deux parametres : resolve et reject.

✏ Syntaxe generale

resolve(valeur) — signale le succes et transmet la valeur.

reject(erreur) — signale l echec et transmet l erreur.

JS
let promesse = new Promise((resolve, reject) => {
  // travail asynchrone
  if (succes) {
    resolve(valeur);   // succes
  } else {
    reject(erreur);    // echec
  }
});

Exemple simple :

JS
let promesse = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("Donnees pretes");
  }, 2000);
});

promesse.then(valeur => console.log(valeur));
// Apres 2 secondes : "Donnees pretes"

Exemple avec condition (fonction reutilisable) :

JS
function verifierAge(age) {
  return new Promise((resolve, reject) => {
    if (age >= 18) {
      resolve("Majeur");
    } else {
      reject("Mineur");
    }
  });
}

verifierAge(20)
  .then(msg => console.log(msg))     // "Majeur"
  .catch(err => console.log(err));

verifierAge(15)
  .then(msg => console.log(msg))
  .catch(err => console.log(err));   // "Mineur"

Exemple — fonction d attente (sans reject) :

JS
function attendre(ms) {
  return new Promise(resolve => {
    setTimeout(resolve, ms);
  });
}

attendre(2000).then(() => console.log("2 secondes passees"));

Pas besoin de reject car il n y a pas d echec possible.

🌐 Exemple concret — distributeur de billets

Un distributeur qui verifie le solde avant de retirer :

JS
function retirer(montant) {
  return new Promise((resolve, reject) => {
    if (montant <= solde) {
      solde -= montant;
      resolve(`Retrait de ${montant} FCFA effectue`);
    } else {
      reject("Solde insuffisant");
    }
  });
}

retirer(5000)
  .then(msg => console.log(msg))
  .catch(err => console.log(err));
18
Chapitre 186 fiches

Promesses

Chainer et coordonner les operations

JS · Fiche Originale

Fiche 186 — catch()
💡 En clair

catch() est appelée quand la Promise est rejetée. Elle reçoit la raison du rejet (souvent une erreur) et évite qu'un échec asynchrone reste sans traitement.

JS
promesse.catch(erreur => {
  console.log("Oups :", erreur);
});

Exemple complet — une Promise qui peut échouer :

JS
function verifierAge(age) {
  return new Promise((resolve, reject) => {
    if (age >= 18) resolve("Majeur");
    else reject("Trop jeune");
  });
}

verifierAge(15)
  .then(msg => console.log(msg))
  .catch(err => console.log("Refusé :", err));
Console
Refusé : Trop jeune
✏️ Ligne par ligne
.catch(err => ...)capture n'importe quel reject survenu avant dans la chaîne
errla valeur passée à reject(), ici la chaîne "Trop jeune"
⚠️ Pièges fréquents
  • Sans .catch(), une Promise rejetée affiche UnhandledPromiseRejection dans la console.
  • .catch() intercepte tous les rejets qui le précèdent dans la chaîne — pas besoin d'en ajouter plusieurs.
💡 Astuce

Place ton .catch() à la fin de la chaîne : il attrapera n'importe quelle erreur survenue avant.

JS · Fiche Originale

Fiche 187 — finally()
💡 En clair

finally() exécute une fonction quoi qu'il arrive — que la Promise soit tenue ou rejetée. Idéale pour libérer des ressources, masquer un loader, fermer une connexion.

JS
promesse
  .then(resultat => ...)
  .catch(erreur => ...)
  .finally(() => {
    console.log("Nettoyage terminé");
  });

Cas pratique — masquer un spinner de chargement :

JS
chargerDonnees()
  .then(data => afficher(data))
  .catch(err => console.log(err))
  .finally(() => {
    document.getElementById("loader").style.display = "none";
  });
✏️ Ligne par ligne
.then(data => afficher(data))traite le cas de succès
.catch(err => console.log(err))traite le cas d'échec
.finally(() => ...)exécuté DANS TOUS LES CAS — succès ou échec
⚠️ Pièges fréquents
  • finally() ne reçoit aucun argument : il ne connaît ni la valeur ni l'erreur.
  • La valeur retournée par finally() est ignorée : elle ne remplace pas la valeur transmise.
💡 Astuce

Utilise .finally() pour tout ce qui doit s'exécuter à la fin, peu importe le résultat : fermer un fichier, cacher un loader, arrêter un timer.

JS · Fiche Originale

Fiche 188 — Chainer des Promises
💡 En clair

Le chaînage permet d'exécuter des opérations asynchrones l'une après l'autre : chaque .then() reçoit le résultat du précédent et peut renvoyer une nouvelle Promise.

JS
premiereEtape()
  .then(r1 => deuxiemeEtape(r1))
  .then(r2 => troisiemeEtape(r2))
  .then(r3 => console.log("Terminé :", r3));

Exemple concret — un pipeline d'authentification :

JS
getUser()
  .then(user => getPermissions(user.id))
  .then(perms => chargerTableauDeBord(perms))
  .then(dashboard => afficher(dashboard))
  .catch(err => console.log("Erreur :", err));
✏️ Ligne par ligne
.then(user => getPermissions(user.id))reçoit l'utilisateur, renvoie une Promise de permissions
.then(perms => chargerTableauDeBord(perms))reçoit les permissions, renvoie une Promise de dashboard
.catch(err => ...)attrape une erreur survenue à n'importe quelle étape
⚠️ Pièges fréquents
  • Si tu oublies le return dans un .then(), l'étape suivante reçoit undefined.
  • Une erreur non attrapée court-circuite tous les .then() suivants et saute directement au prochain .catch().
💡 Astuce

Renvoie une Promise depuis .then() : JavaScript attendra sa résolution avant d'appeler le prochain .then(). C'est ce qui fait fonctionner le chaînage.

JS · Fiche Originale

Fiche 189 — Promise.all()
💡 En clair

Promise.all() lance plusieurs Promesses en parallèle et attend qu'elles toutes réussissent. Elle renvoie un tableau avec les résultats dans l'ordre.

JS
Promise.all([p1, p2, p3])
  .then(([r1, r2, r3]) => {
    console.log(r1, r2, r3);
  })
  .catch(err => console.log("L'une a échoué :", err));

Exemple — charger 3 profils en parallèle :

JS
Promise.all([
  fetch("/api/users/1").then(r => r.json()),
  fetch("/api/users/2").then(r => r.json()),
  fetch("/api/users/3").then(r => r.json()),
])
  .then(users => console.log(users));
// [user1, user2, user3] dans l'ordre, beaucoup plus vite qu'en séquentiel
Console
[ { id: 1, nom: "Awa" }, { id: 2, nom: "Moussa" }, { id: 3, nom: "Fatou" } ]
✏️ Ligne par ligne
Promise.all([...])attend que TOUTES les Promesses réussissent
.then(([r1, r2, r3]) => ...)destructuration : on récupère les 3 résultats dans l'ordre
.catch(err => ...)si UNE SEULE échoue → tout le Promise.all est rejeté
⚠️ Pièges fréquents
  • Dès qu'une seule Promesse échoue, Promise.all() est rejetée immédiatement, sans attendre les autres.
  • Les Promesses restantes continuent de tourner en arrière-plan — elles ne sont pas annulées.
💡 Astuce

Si toutes tes Promesses sont indépendantes, utilise Promise.all() plutôt que de les await l'une après l'autre : c'est beaucoup plus rapide.

JS · Fiche Originale

Fiche 190 — Promise.allSettled()
💡 En clair

Promise.allSettled() attend la fin de toutes les Promesses, qu'elles réussissent ou échouent. Elle renvoie un tableau décrivant l'état de chacune.

JS
Promise.allSettled([p1, p2, p3])
  .then(resultats => console.log(resultats));

Chaque résultat a la forme { status, value } ou { status, reason } :

JS
Promise.allSettled([
  Promise.resolve("OK 1"),
  Promise.reject("Échec 2"),
  Promise.resolve("OK 3"),
]).then(resultats => {
  resultats.forEach(r => console.log(r.status, r.value || r.reason));
});
Console
fulfilled OK 1
rejected Échec 2
fulfilled OK 3
✏️ Ligne par ligne
Promise.allSettled([...])attend TOUS les résultats, peu importe succès ou échec
r.statusvaut "fulfilled" (succès) ou "rejected" (échec)
r.valueprésent si succès — la valeur résolue
r.reasonprésent si échec — la raison du rejet
⚠️ Pièges fréquents
  • Promise.allSettled() ne se rejette jamais : elle réussit toujours, même si toutes les Promesses internes échouent.
  • Contrairement à Promise.all(), il n'y a pas de court-circuit : on attend la fin de toutes les Promesses.
💡 Astuce

Utilise Promise.allSettled() quand tu veux le résultat de toutes les opérations, même si certaines échouent (ex : importer plusieurs fichiers,某些 pouvant être corrompus).

JS · Fiche Originale

Fiche 192 — Promise.any()
💡 En clair

Promise.any() attend la première Promesse qui réussit et renvoie sa valeur. Si elles échouent toutes, elle est rejetée avec une AggregateError.

JS
Promise.any([p1, p2, p3])
  .then(premierSucces => console.log("Gagné :", premierSucces))
  .catch(err => console.log("Toutes ont échoué :", err.errors));

Cas d'usage — tester plusieurs miroirs d'un service :

JS
Promise.any([
  fetch("https://miroir1.api.com/data"),
  fetch("https://miroir2.api.com/data"),
  fetch("https://miroir3.api.com/data"),
])
  .then(res => res.json())
  .then(data => console.log(data));
// Le premier miroir à répondre l'emporte
✏️ Ligne par ligne
Promise.any([...])renvoie la valeur de la première Promesse qui réussit
.then(premierSucces => ...)reçoit la valeur de la première tenue
.catch(err => err.errors)AggregateError : tableau de toutes les raisons d'échec
⚠️ Pièges fréquents
  • Si toutes les Promesses sont rejetées, Promise.any() lance une AggregateError (et non la raison individuelle).
  • À la différence de Promise.race(), Promise.any() ignore les rejets tant qu'une Promesse peut encore réussir.
💡 Astuce

Utilise Promise.any() pour gagner en rapidité : on prend la première réponse positive, on ignore les échecs.

19
Chapitre 194 fiches

async / await

Ecrire l asynchrone avec un flux lisible

JS · Fiche Originale

Fiche 193 — async
💡 En clair

Le mot-clé async placé devant une fonction la transforme : elle renvoie toujours une Promise. Si tu renvoies une valeur, elle est automatiquement emballée dans une Promise résolue.

JS
async function saluer() {
  return "Bonjour";
}

saluer().then(msg => console.log(msg));
// "Bonjour"

Une fonction async renvoie toujours une Promise, même sans expliciter Promise.resolve() :

JS
// Équivalent à :
function saluer() {
  return Promise.resolve("Bonjour");
}
Console
Bonjour
✏️ Ligne par ligne
async function saluer() { ... }préfixe async → la fonction renvoie une Promise
return "Bonjour";la valeur de retour devient la valeur résolue de la Promise
saluer().then(msg => ...)comme toute Promise, on l'attend avec .then()
⚠️ Pièges fréquents
  • Une fonction async qui ne contient pas d'await reste synchrone à l'intérieur — seule la valeur de retour est transformée en Promise.
  • Les fonctions fléchées aussi acceptent async : const saluer = async () => "Bonjour";
💡 Astuce

Marque async toute fonction qui utilise await à l'intérieur — sinon JavaScript refuse de compiler.

JS · Fiche Originale

Fiche 194 — await
💡 En clair

await met en pause l'exécution d'une fonction async jusqu'à ce que la Promise soit résolue. Il renvoie directement la valeur — fini les .then() imbriqués.

JS
async function charger() {
  let data = await fetch("/api/users");
  let users = await data.json();
  console.log(users);
}

Comparaison : même logique avec .then() vs await :

JS
// Avec .then()
fetch("/api/users")
  .then(r => r.json())
  .then(users => console.log(users));

// Avec await (plus lisible)
async function charger() {
  let r = await fetch("/api/users");
  let users = await r.json();
  console.log(users);
}
✏️ Ligne par ligne
await fetch("/api/users")met en pause charger() jusqu'à la réponse, puis renvoie la Response
await r.json()attend le parsing JSON, puis renvoie les données
async function charger()obligatoire : await ne peut être utilisé que dans une fonction async
⚠️ Pièges fréquents
  • await ne peut être utilisé qu'à l'intérieur d'une fonction async (au niveau top-level uniquement dans les modules ES).
  • await ne bloque pas le reste du programme : la fonction async est suspendue, mais l'event loop continue de tourner.
💡 Astuce

Compose await avec une affectation : const data = await promesse — c'est ce qui rend le code asynchrone aussi lisible que du code synchrone.

JS · Fiche Originale

Fiche 195 — async/await/try/catch
💡 En clair

Avec async/await, on gère les erreurs comme en code synchrone : un bloc try/catch autour des await capture les rejets.

JS
async function chargerUser(id) {
  try {
    let res = await fetch(`/api/users/${id}`);
    if (!res.ok) throw new Error("HTTP " + res.status);
    let user = await res.json();
    return user;
  } catch (err) {
    console.log("Erreur :", err.message);
    return null;
  }
}

Sans try/catch, l'erreur deviendrait une UnhandledPromiseRejection.

Console
Erreur : HTTP 404
✏️ Ligne par ligne
try { ... }englobe les opérations qui peuvent échouer
let res = await fetch(...)si la Promise est rejetée → saute directement au catch
throw new Error("HTTP " + res.status)on peut aussi lever sa propre erreur pour un cas métier
catch (err) { ... }reçoit l'erreur (objet Error ou valeur passée à reject())
⚠️ Pièges fréquents
  • Oublier le try/catch autour d'un await qui échoue → UnhandledPromiseRejection et crash du programme.
  • Le catch ne capture que les erreurs survenues après son ouverture : place-le au bon niveau.
💡 Astuce

Encapsule les séries d'await critiques dans un seul try/catch global pour garder un code lisible et centraliser la gestion d'erreur.

JS · Fiche Originale

Fiche 196 — .then() vs async/await
💡 En clair

.then() et async/await sont deux styles pour faire la même chose. async/await est du sucre syntaxique sur les Promesses : sous le capot, c'est identique.

JS
// Style .then()
function charger() {
  return fetch("/api/users")
    .then(r => r.json())
    .then(users => users.filter(u => u.actif))
    .then(actifs => console.log(actifs));
}

// Style async/await
async function charger() {
  let r = await fetch("/api/users");
  let users = await r.json();
  let actifs = users.filter(u => u.actif);
  console.log(actifs);
}
✏️ Ligne par ligne
return fetch(...).then(...).then(...)chaîne de Promesses — imbriquée si logique complexe
let r = await fetch(...)lecture séquentielle, proche du code synchrone
async function charger()le mot-clé async autorise l'usage d'await
⚠️ Pièges fréquents
  • Les deux styles cohabitent : tu peux écrire .then() sur une fonction async ou utiliser await sur une fonction qui renvoie une Promise classique.
  • Pour paralléliser plusieurs appels, combine Promise.all() avec await : await Promise.all([...]).
💡 Astuce

Préfère async/await pour la lisibilité, mais garde .then() pour les transformations simples en une ligne (ex : fetch().then(r => r.text())).

20
Chapitre 207 fiches

Execution JavaScript

Call stack, files et ordre d execution

JS · Fiche Originale

Fiche 197 — Execution sequentielle
💡 En clair

En exécution séquentielle, chaque opération attend la fin de la précédente. Simple à comprendre, mais lent quand les opérations sont indépendantes.

JS
async function chargerTout() {
  let u1 = await fetch("/api/users/1").then(r => r.json());
  let u2 = await fetch("/api/users/2").then(r => r.json());
  let u3 = await fetch("/api/users/3").then(r => r.json());
  return [u1, u2, u3];
}

Les 3 requêtes s'enchaînent : la 2e ne démarre que quand la 1re est finie.

Console
Requête 1... (300 ms)
Requête 2... (300 ms)
Requête 3... (300 ms)
Total : 900 ms
✏️ Ligne par ligne
let u1 = await fetch(...)attend la fin de la 1re requête avant de continuer
let u2 = await fetch(...)ne démarre qu'après u1 — perte de temps si indépendantes
return [u1, u2, u3]tous les résultats prêts seulement à la fin
⚠️ Pièges fréquents
  • L'exécution séquentielle est lente quand les opérations sont indépendantes : chaque await bloque la suite.
  • À ne confondre avec l'ordre des instructions synchrones : await met en pause la fonction async, pas le reste du programme.
💡 Astuce

Si les opérations sont dépendantes (la 2e a besoin de la 1re), reste en séquentiel. Sinon, passe à Promise.all().

JS · Fiche Originale

Fiche 198 — Execution parallele
💡 En clair

En exécution parallèle, plusieurs Promesses sont lancées en même temps avec Promise.all(). On attend la plus lente, pas la somme de toutes.

JS
async function chargerTout() {
  let [u1, u2, u3] = await Promise.all([
    fetch("/api/users/1").then(r => r.json()),
    fetch("/api/users/2").then(r => r.json()),
    fetch("/api/users/3").then(r => r.json()),
  ]);
  return [u1, u2, u3];
}
Console
Requêtes 1, 2, 3 lancées en parallèle...
Total : 300 ms (au lieu de 900 ms)
✏️ Ligne par ligne
Promise.all([...])lance toutes les Promesses simultanément
await Promise.all(...)attend que TOUTES soient résolues
let [u1, u2, u3] = ...destructuration du tableau résultat dans l'ordre initial
⚠️ Pièges fréquents
  • Dès qu'une Promesse échoue, Promise.all() est rejetée immédiatement — les autres continuent en arrière-plan mais leurs résultats sont ignorés.
  • Les Promesses ne sont pas réellement "parallèles" au sens multi-thread : elles sont concurrentes sur l'event loop mono-thread de JS.
💡 Astuce

Pour paralléliser : lance les Promesses SANS await d'abord, puis await leurs résultats collectivement. C'est l'astuce derrière Promise.all().

JS · Fiche Originale

Fiche 199 — Event Loop
💡 En clair

L'Event Loop est le mécanisme qui permet à JavaScript (mono-thread) de gérer plusieurs tâches sans bloquer. Elle vérifie en continu : "La pile est vide ? Je prends la prochaine tâche en file d'attente."

JS
console.log("1");
setTimeout(() => console.log("2"), 0);
console.log("3");
Console
1
3
2

L'ordre surprend : le 2 arrive en dernier bien qu'il soit planifié avant le 3.

✏️ Ligne par ligne
console.log("1")synchrone → exécuté immédiatement
setTimeout(() => ..., 0)planifie un callback — ne bloque pas la suite
console.log("3")synchrone → exécuté pendant que le timer attend
callback setTimeoutlancé uniquement quand la pile est vide et son délai écoulé
⚠️ Pièges fréquents
  • L'Event Loop ne traite qu'une tâche à la fois : un calcul long bloque toutes les autres tâches en attente.
  • Les callbacks ne s'exécutent jamais au milieu d'une fonction synchrone : ils attendent toujours que la pile soit vide.
💡 Astuce

Pense à l'Event Loop comme à un serveur de restaurant : il prend une commande, la transmet en cuisine, et pendant que ça cuit il prend la suivante. Il ne bloque jamais devant la cuisine.

JS · Fiche Originale

Fiche 200 — Call Stack
💡 En clair

La Call Stack (pile d'appels) est la structure qui empile les fonctions en cours d'exécution. Quand une fonction est appelée, elle est empilée ; quand elle se termine, elle est dépilée.

JS
function saluer(nom) {
  return "Bonjour " + nom;
}

function demarrer() {
  let msg = saluer("Awa");
  console.log(msg);
}

demarrer();
Console
Bonjour Awa
✏️ Ligne par ligne
demarrer() est appelée→ empilée : [demarrer]
let msg = saluer("Awa")→ saluer est empilée : [demarrer, saluer]
return "Bonjour " + nom→ saluer se termine, elle est dépilée : [demarrer]
console.log(msg)→ après exécution, demarrer est dépilée : []
⚠️ Pièges fréquents
  • Une pile trop profonde provoque RangeError: Maximum call stack size exceeded (souvent à cause d'une récursion infinie).
  • Tant que la Call Stack n'est pas vide, l'Event Loop ne prend pas de nouvelle tâche dans les files.
💡 Astuce

Pour déboguer un crash "stack overflow", cherche la fonction récursive qui ne s'arrête jamais — c'est elle qui remplit la pile.

JS · Fiche Originale

Fiche 201 — Task Queue
💡 En clair

La Task Queue (aussi appelée macrotask queue ou callback queue) contient les callbacks prêts à s'exécuter : timers expirés, événements DOM, callbacks réseau. L'Event Loop y puise quand la pile est vide.

JS
console.log("A");
setTimeout(() => console.log("B"), 0);
console.log("C");
// Le callback de setTimeout va en Task Queue
// et ne s'exécute que quand la pile est vide
Console
A
C
B
✏️ Ligne par ligne
console.log("A")empilé, exécuté, dépilé
setTimeout(() => console.log("B"), 0)callback planifié — il va dans la Task Queue
console.log("C")empilé, exécuté, dépilé — prioritaire sur la file
callback "B"récupéré par l'Event Loop uniquement quand la pile est vide
⚠️ Pièges fréquents
  • setTimeout(fn, 0) n'exécute pas fn immédiatement : il attend que la pile soit vide ET que la microtask queue soit vide.
  • Les tâches macrotask sont moins prioritaires que les microtasks (Promesses) — elles passent toujours après.
💡 Astuce

Sources typiques de macrotasks : setTimeout, setInterval, setImmediate (Node), I/O, fetch, événements UI. Pour des priorités plus hautes, regarde du côté des microtasks.

JS · Fiche Originale

Fiche 202 — Microtask Queue
💡 En clair

La Microtask Queue contient les callbacks des Promesses (.then(), .catch(), .finally()) et de queueMicrotask(). Elle est vidée entièrement entre deux macrotasks.

JS
console.log("A");
setTimeout(() => console.log("B"), 0);
Promise.resolve().then(() => console.log("C"));
console.log("D");
Console
A
D
C
B
✏️ Ligne par ligne
console.log("A")synchrone, exécuté en premier
setTimeout(..., 0)callback → macrotask queue (priorité basse)
Promise.resolve().then(...)callback → microtask queue (priorité haute)
console.log("D")synchrone, exécuté avant les files
Ordre finalA, D (synchro) → C (microtask) → B (macrotask)
⚠️ Pièges fréquents
  • Une chaîne infinie de microtasks peut bloquer indéfiniment l'Event Loop : les macrotasks (timers, UI) ne s'exécuteront jamais.
  • Les microtasks s'exécutent avant le rendu visuel — pratique pour mettre à jour le DOM sans scintillement.
💡 Astuce

Règle d'or : synchrone > microtask (Promises) > macrotask (setTimeout, I/O). Toujours dans cet ordre.

JS · Fiche Originale

Fiche 203 — Comprendre l ordre d execution
💡 En clair

Pour prédire l'ordre d'exécution, suis cette règle : 1) code synchrone (Call Stack), puis 2) toutes les microtasks, puis 3) une seule macrotask, et on recommence.

JS
console.log("1 synchrone");
setTimeout(() => console.log("5 macrotask"), 0);
Promise.resolve()
  .then(() => console.log("3 microtask"))
  .then(() => console.log("4 microtask"));
console.log("2 synchrone");
Console
1 synchrone
2 synchrone
3 microtask
4 microtask
5 macrotask
✏️ Ligne par ligne
console.log("1 ...")synchrone → pile exécutée immédiatement
setTimeout(..., 0)callback mis en MACROTASK queue
Promise.resolve().then(...).then(...)2 callbacks mis en MICROTASK queue
console.log("2 ...")synchrone, exécuté avant les files
// ensuitevide toutes les microtasks (3, 4) puis UNE macrotask (5)
⚠️ Pièges fréquents
  • Les .then() s'exécutent toujours avant le prochain setTimeout, même avec délai 0.
  • Entre deux macrotasks, l'Event Loop vide entièrement la microtask queue — y compris celles ajoutées par d'autres microtasks.
💡 Astuce

Devine l'ordre avant de tester. Cette compétence est indispensable pour déboguer des bugs subtils en asynchrone.

21
Chapitre 2111 fiches

Modules

Exporter, importer et organiser le code

JS · Fiche Originale

Fiche 204 — Pourquoi les modules ?
💡 En clair

Un module est un fichier JavaScript qui expose un morceau de code réutilisable. Les modules évitent le grand fichier unique illisible : on découpe le code par fonctionnalité, on importe ce dont on a besoin.

📖 Mots à connaître
moduleun fichier JS qui exporte des valeurs (fonctions, classes, constantes) et peut en importer d'autres
exportmot-clé pour rendre une valeur disponible depuis l'extérieur
importmot-clé pour utiliser une valeur exportée par un autre module
dépendanceun module A qui importe un module B dépend de B
JS
// Avant : tout dans un fichier de 1000 lignes

// Après : découpé en modules
// math.js
export function additionner(a, b) { return a + b; }

// app.js
import { additionner } from "./math.js";
console.log(additionner(2, 3)); // 5
Console
5
⚠️ Pièges fréquents
  • Sans modules, toutes les variables globales entrent en collision : c'est le chaos dès qu'un projet grandit.
  • Les modules ES sont en mode strict par défaut — pas besoin d'écrire "use strict";.
💡 Astuce

Un module = une responsabilité. Si un fichier fait trop de choses, divise-le en modules plus petits et nommés clairement.

JS · Fiche Originale

Fiche 205 — export
💡 En clair

Le mot-clé export rend une valeur disponible depuis l'extérieur du module. On peut l'écrire devant la déclaration (export inline) ou à la fin (export en bloc). Tout ce qui n'est pas exporté reste privé au module — c'est l'encapsulation native.

JS
// math.js

// 1) Export inline (devant la déclaration)
export function additionner(a, b) { return a + b; }
export const PI = 3.14;

// 2) Export en bloc (à la fin)
function multiplier(a, b) { return a * b; }
function soustraire(a, b) { return a - b; }
export { multiplier, soustraire };

// 3) Export par défaut (un seul par module)
export default function calculer(x) {
  return x * PI;
}
✏️ Ligne par ligne
export function additionner(...)export inline — exporte ET déclare en même temps.
export { multiplier, soustraire }export en bloc — pratique pour grouper en fin de fichier.
export default function ...export par défaut — un seul par module. Voir fiche 206.

Rappel : ce qui n'est PAS exporté reste privé au module :

JS
// math.js
const TAUX_TVA = 0.18;  // privé — non exporté
function interne() { /* ... */ }  // privé

export function prixTTC(prix) {
  return prix * (1 + TAUX_TVA);  // utilise les privés en interne
}
📖 Mots à connaître
exportmot-clé pour rendre une valeur accessible depuis l'extérieur.
export defaultexporte une valeur "par défaut" — importable sans accolades. Voir fiche 206.
modulefichier JavaScript isolé — ses variables ne fuient pas vers les autres.
⚠️ Pièges fréquents
  • Un module ne peut avoir qu'un seul export default — pas plus, sinon SyntaxError.
  • Les exports doivent être au niveau racine du module — pas dans une fonction ou un if. Sinon, SyntaxError.
💡 Astuce

Rappel : voir la fiche 204 sur l'import pour consommer ces exports, et la fiche 206 sur l'export default.

JS · Fiche Originale

Fiche 206 — import
💡 En clair

import récupère une valeur exportée par un autre module. La syntaxe dépend du type d'export (nommé ou défaut), mais l'idée reste la même : indiquer quoi importer et depuis quel fichier.

JS
// Import nommé
import { additionner, PI } from "./math.js";

// Import par défaut (sans accolades)
import saluer from "./salut.js";

// Import combiné
import saluer, { PI } from "./salut.js";

// Tout importer sous un namespace
import * as math from "./math.js";
console.log(math.additionner(2, 3));
Console
5
✏️ Ligne par ligne
import { additionner, PI } from "./math.js"récupère les exports nommés entre accolades
import saluer from "./salut.js"sans accolades : importe le default export
import * as math from ...récupère tous les exports sous un objet namespace
⚠️ Pièges fréquents
  • Les imports sont hoistés : ils sont exécutés en premier, peu importe leur position dans le fichier.
  • En ES modules, l'extension .js est obligatoire dans le chemin (contrairement à CommonJS).
💡 Astuce

Place toujours tes imports en haut de fichier — c'est la convention universelle et ça évite les surprises.

JS · Fiche Originale

Fiche 207 — Named export
💡 En clair

Un named export exporte une valeur par son nom. On peut en avoir plusieurs par module. À l'import, on cite le nom exact entre accolades.

JS
// utils.js
export function formaterDate(d) { return d.toLocaleDateString(); }
export function formaterPrix(p) { return p.toFixed(2) + " FCFA"; }
export const VERSION = "1.0.0";

// app.js
import { formaterDate, VERSION } from "./utils.js";
console.log(VERSION, formaterDate(new Date()));
Console
1.0.0 12/03/2025
✏️ Ligne par ligne
export function formaterDate(...)export nommé — accessible via import { formaterDate }
export const VERSION = "1.0.0";export nommé d'une constante
import { formaterDate, VERSION }les noms doivent correspondre EXACTEMENT aux exports
⚠️ Pièges fréquents
  • Le nom à l'import doit strictement correspondre au nom exporté. import { formatDate } ne marchera pas si l'export est formaterDate.
  • Pour éviter les conflits, utilise la syntaxe de renommage : import { formaterDate as fmtDate }.
💡 Astuce

Les named exports sont parfaits pour les bibliothèques utilitaires : l'IDE peut vérifier les noms et suggérer l'auto-complétion.

JS · Fiche Originale

Fiche 208 — Default export
💡 En clair

Un default export exporte une seule valeur "principale" par module. À l'import, pas besoin d'accolades : tu choisis le nom que tu veux.

JS
// saluer.js
export default function saluer(nom) {
  return "Bonjour " + nom;
}

// app.js
import saluer from "./saluer.js";
// ou : import bonjour from "./saluer.js"; (nom libre)
console.log(saluer("Awa"));
Console
Bonjour Awa
✏️ Ligne par ligne
export default function saluer(nom)définit la valeur principale du module
import saluer from "./saluer.js"sans accolades — nom libre à l'import
import bonjour from ...aurait aussi marché : le nom est choisi par l'importateur
⚠️ Pièges fréquents
  • Un seul default export par module. Sinon : SyntaxError: Duplicate export of 'default'.
  • Mélanger default + named est possible mais source de confusion : import def, { named } from ...
💡 Astuce

Le default export est idéal pour un module qui expose une chose principale : une classe (ex : export default class User) ou un composant React.

JS · Fiche Originale

Fiche 209 — Renommer un import
💡 En clair

Pour éviter les conflits de noms ou clarifier un nom trop générique, on renomme à l'import avec le mot-clé as.

JS
// utils.js
export function log(msg) { console.log(msg); }

// logger.js
export function log(msg) { console.log("[LOG]", msg); }

// app.js
import { log as consoleLog } from "./utils.js";
import { log as loggerLog } from "./logger.js";
consoleLog("simple");
loggerLog("préfixé");
Console
simple
[LOG] préfixé
✏️ Ligne par ligne
import { log as consoleLog }récupère l'export "log" et le renomme en "consoleLog"
import { log as loggerLog }même export "log" d'un autre module, nom différent
consoleLog("simple")utilise le premier log sous son nouveau nom
⚠️ Pièges fréquents
  • Le renommage ne modifie pas le module source : il ne fait que choisir un autre nom local.
  • Tu peux aussi renommer à l'export : export { log as consoleLog };.
💡 Astuce

Renomme systématiquement quand deux modules exportent le même nom — c'est plus propre que d'importer avec un namespace complet.

JS · Fiche Originale

Fiche 210 — Importer plusieurs elements
💡 En clair

Quand un module expose plusieurs valeurs nommées, on peut les importer en une seule instruction avec la syntaxe import { a, b, c } from "..." — séparées par des virgules entre accolades. Plus concis et plus lisible qu'un import par ligne.

JS
// Avant : un import par ligne
import { additionner } from "./math.js";
import { multiplier } from "./math.js";
import { PI } from "./math.js";

// Après : groupé
import { additionner, multiplier, PI } from "./math.js";

console.log(PI);
console.log(additionner(2, 3));
console.log(multiplier(4, 5));
Console
3.14
5
20
✏️ Ligne par ligne
import { a, b, c } from "./math.js"importe 3 valeurs nommées en une seule instruction.
additionner(2, 3)appelable immédiatement après l'import.
PIconstante importée — en lecture seule.

On peut aussi renommer pendant l'import pour éviter les conflits :

JS
// Deux modules avec une fonction "calculer" chacun
import { calculer as calculerV1 } from "./math-v1.js";
import { calculer as calculerV2 } from "./math-v2.js";

console.log(calculerV1(5));
console.log(calculerV2(5));
Console
...

On peut même tout importer sous un namespace :

JS
import * as Math from "./math.js";

console.log(Math.additionner(2, 3));
console.log(Math.PI);
console.log(Math.multiplier(4, 5));
📖 Mots à connaître
import groupésyntaxe import { a, b, c } pour plusieurs valeurs nommées.
alias (as)nom as alias pour renommer à l'import et éviter les conflits.
namespaceimport * as Nom pour regrouper tous les exports sous un objet.
⚠️ Pièges fréquents
  • Les imports sont hisés en haut du fichier — il est d'usage de les regrouper au début, jamais au milieu du code.
  • console.log(...) dans un module n'a pas d'effet de bord visible tant qu'on n'importe pas le module — il faut l'importer pour déclencher son exécution.
💡 Astuce

Rappel : voir la fiche 205 sur export pour préparer les valeurs à importer, et la fiche 209 sur l'import default.

JS · Fiche Originale

Fiche 211 — Reexporter
💡 En clair

Re-exporter = prendre les exports d'un module et les exposer depuis un autre. Utile pour construire une façade (un fichier unique qui regroupe plusieurs sous-modules).

JS
// math/index.js — façade
export { additionner, soustraire } from "./operations.js";
export { multiplier, diviser } from "./avance.js";
export { default as calculatrice } from "./calc.js";

// app.js — un seul import
import { additionner, multiplier, calculatrice } from "./math/index.js";
✏️ Ligne par ligne
export { additionner, soustraire } from "./operations.js"re-export sans consommer localement
export { default as calculatrice } from "./calc.js"renommage du default export pour le nommer
import { ... } from "./math/index.js"un seul point d'entrée pour tout le sous-module math
⚠️ Pièges fréquents
  • Le re-export ne rend PAS la valeur disponible dans le module courant — il faut l'importer séparément si tu veux l'utiliser.
  • Pour re-exporter TOUT d'un coup : export * from "./operations.js"; (mais les default exports ne sont pas repris).
💡 Astuce

Convention : crée un index.js par dossier qui re-exporte tout. Les imports deviennent import { ... } from "./math" — propre.

JS · Fiche Originale

Fiche 212 — Import dynamique
💡 En clair

L'import dynamique charge un module à la demande, au moment où on en a besoin. Il renvoie une Promise qui se résout avec le module — idéal pour réduire la taille initiale d'une app.

JS
// Au lieu d'importer tout de suite :
// import lourd from "./module-lourd.js";

// On charge à la demande
bouton.addEventListener("click", async () => {
  const module = await import("./module-lourd.js");
  module.faireQuelqueChose();
});
✏️ Ligne par ligne
await import("./module-lourd.js")renvoie une Promise résolue avec le module
module.faireQuelqueChose()accède aux exports comme à un objet
// ne se charge qu'au clicle module n'est téléchargé que lorsqu'on clique
⚠️ Pièges fréquents
  • L'import dynamique n'évite pas les imports statiques si tu les as déjà écrits en haut du fichier — ils sont analysés au parsing.
  • En Node.js, l'import dynamique renvoie aussi une Promise, même en CommonJS.
💡 Astuce

Cas d'usage typique : lazy-loading de routes dans une SPA, modules graphiques chargés seulement si l'utilisateur ouvre un graphique, éditeurs riches chargés au clic.

JS · Fiche Originale

Fiche 213 — Modules et classes
💡 En clair

Une classe peut être exportée comme n'importe quelle autre valeur. Importer une classe permet de l'instancier (new) depuis un autre fichier.

JS
// User.js
export class User {
  constructor(nom, age) {
    this.nom = nom;
    this.age = age;
  }
  saluer() { return "Bonjour, je suis " + this.nom; }
}

// app.js
import { User } from "./User.js";
const u = new User("Awa", 25);
console.log(u.saluer());
Console
Bonjour, je suis Awa
✏️ Ligne par ligne
export class User { ... }rend la classe disponible à l'extérieur du module
import { User } from "./User.js"importe la classe (avec accolades = named export)
const u = new User("Awa", 25)instancie un objet de cette classe
⚠️ Pièges fréquents
  • Une classe exportée en named s'importe avec accolades : import { User }. En default, sans accolades : import User from ....
  • Les classes ne sont pas hoistées : on ne peut pas les instancier avant leur déclaration dans le même fichier.
💡 Astuce

Convention : un fichier par classe, nommé comme la classe (User.js exporte class User). C'est la norme dans la plupart des frameworks.

JS · Fiche Originale

Fiche 214 — Organisation d un projet
💡 En clair

Un projet bien organisé découpe son code en modules cohérents, regroupés par fonctionnalité. Chaque dossier expose une façade (index.js) qui masque les détails internes.

JS
// Structure recommandée
// src/
//   user/
//     index.js     → façade qui re-exporte
//     User.js      → classe
//     userService.js
//   product/
//     index.js
//     Product.js
//   app.js

// src/user/index.js
export { User } from "./User.js";
export { creerUser } from "./userService.js";

// src/app.js
import { User, creerUser } from "./user/index.js";
import { Product } from "./product/index.js";
✏️ Ligne par ligne
src/user/index.jsfaçade qui regroupe les exports du dossier user
export { User } from "./User.js"re-export depuis la façade
import { User, creerUser } from "./user/index.js"point d'entrée unique pour tout ce qui concerne les users
⚠️ Pièges fréquents
  • Ne mets pas tout dans app.js au nom de la simplicité : ça devient ingérable dès qu'on dépasse 500 lignes.
  • Évite les imports circulaires (A importe B qui importe A) : sources de bugs subtils et d'initialisations partielles.
💡 Astuce

Règle d'or : un fichier = une responsabilité. Si un fichier fait plus de 200 lignes, demande-toi s'il ne devrait pas être découpé en modules.

22
Chapitre 2217 fiches

DOM et navigateur

Lire et modifier la page

JS · Fiche Originale

Fiche 215 — DOM : definition
💡 En clair

DOM signifie Document Object Model (Modele d Objet du Document).

C est une representation en memoire de ta page HTML, sous forme d arbre d objets. JavaScript peut lire et modifier cet arbre pour changer la page en direct, sans la recharger.

A quoi ca ressemble ? Quand le navigateur charge ce HTML :

HTML
<!DOCTYPE html>
<html>
  <head>
    <title>Ma page</title>
  </head>
  <body>
    <h1 id="titre">Bonjour</h1>
    <p class="texte">Un paragraphe</p>
  </body>
</html>

Il cree cet arbre DOM :

Arbre DOM
document
 +-- html
      |-- head
      |    +-- title
      |         +-- "Ma page"
      +-- body
           |-- h1#titre
           |    +-- "Bonjour"
           +-- p.texte
                +-- "Un paragraphe"

Chaque balise HTML devient un objet JavaScript qu on peut manipuler.

🔗 Le point d entree : document

document est l objet qui represente toute la page. C est par lui qu on accede a tout le reste :

JS
console.log(document.title);      // "Ma page"
console.log(document.body);       // <body>...</body>
📖 Pourquoi c est utile
Modifier le contenuChanger la page sans recharger
Reagir aux actionsClic, saisie clavier, scroll...
Creer / supprimerAjouter ou retirer des elements dynamiquement
Changer le styleModifier l apparence en direct
🌐 Exemple concret

Quand tu cliques sur J aime sur Facebook, la page ne se recharge pas. JavaScript modifie le DOM : le compteur augmente, le bouton change de couleur. Tout ca se passe en memoire, pas dans le fichier HTML.

JS · Fiche Originale

Fiche 216 — Selectionner un element
💡 En clair

Avant de modifier un element, il faut d abord le selectionner (le trouver dans le DOM).

JavaScript propose 5 methodes principales pour selectionner des elements.

📖 Les methodes principales
getElementById()Par id — retourne 1 element
querySelector()Par selecteur CSS — retourne 1 element
querySelectorAll()Par selecteur CSS — retourne une liste (NodeList)
getElementsByClassName()Par classe — retourne une HTMLCollection
getElementsByTagName()Par balise — retourne une HTMLCollection
✏ Syntaxe generale

JS
document.getElementById("titre")
document.querySelector(".texte")
document.querySelectorAll("p")

Exemple — getElementById :

HTML
<h1 id="titre">Bonjour</h1>
JS
let titre = document.getElementById("titre");
console.log(titre.textContent); // "Bonjour"

Exemple — querySelector (accepte n importe quel selecteur CSS) :

JS
document.querySelector("h1")              // premiere balise <h1>
document.querySelector(".texte")         // premier element avec class="texte"
document.querySelector("#titre")          // element avec id="titre"
document.querySelector("div p")           // premier <p> dans un <div>
document.querySelector('input[type=text]')  // input de type text
⚠ Attention

querySelector retourne seulement le premier element trouve. Pour tous les recuperer, utilise querySelectorAll (voir fiche 216b).

Exemple — querySelectorAll :

JS
let paragraphes = document.querySelectorAll(".texte");
console.log(paragraphes.length); // 3

paragraphes.forEach(p => {
  console.log(p.textContent); // "Un", "Deux", "Trois"
});
🌐 Exemple concret

Sur un site de blog, pour selectionner tous les titres d articles :

JS
let titres = document.querySelectorAll(".article h2");
titres.forEach(titre => {
  console.log(titre.textContent);
});

JS · Fiche Originale

Fiche 216a — querySelector
💡 En clair

querySelector(selecteur) retourne le premier element qui correspond au selecteur CSS donne, ou null si rien n est trouve.

✏ Syntaxe generale

document.querySelector(selecteurCSS)

Le parametre est une chaine contenant n importe quel selecteur CSS valide (comme en CSS).

JS
document.querySelector("h1")             // premiere balise <h1>
document.querySelector(".texte")         // premier element avec class="texte"
document.querySelector("#titre")          // element avec id="titre"
document.querySelector("div p")          // premier <p> dans un <div>
document.querySelector('input[type="text"]')  // input de type text

Exemple :

JS
let titre = document.querySelector("#titre");
console.log(titre.textContent); // "Bonjour"

let premierParagraphe = document.querySelector("p");
console.log(premierParagraphe.textContent);
📖 Selecteurs CSS les plus utiles
"tag"Par balise : "h1", "p", "div"
".classe"Par classe : ".texte"
"#id"Par id : "#titre"
"parent enfant"Descendance : "div p"
"[attr=val]"Par attribut : "[type=text]"
⚠ Piege

querySelector retourne un seul element (le premier trouve). Si tu veux tous les elements, utilise querySelectorAll (fiche 216b).

Si aucun element ne correspond, la methode retourne null. Verifie toujours le resultat avant de l utiliser :

JS
let el = document.querySelector(".inexistant");
if (el) {
  el.textContent = "OK";
} else {
  console.log("Element introuvable");
}
🌐 Exemple concret

Selectionner le bouton principal d une page pour y attacher un ecouteur de clic :

JS
let bouton = document.querySelector("button.btn-principal");
bouton.addEventListener("click", () => {
  console.log("Clique !");
});

JS · Fiche Originale

Fiche 216b — querySelectorAll
💡 En clair

querySelectorAll(selecteur) retourne une NodeList contenant tous les elements qui correspondent au selecteur CSS. Si rien n est trouve, la liste est vide (longueur 0).

✏ Syntaxe generale

document.querySelectorAll(selecteurCSS) — meme syntaxe que querySelector, mais retourne tous les elements trouves.

JS
let elements = document.querySelectorAll(selecteur);

elements.forEach(el => {
  // traiter chaque element
});

Exemple :

HTML
<p class="texte">Un</p>
<p class="texte">Deux</p>
<p class="texte">Trois</p>
JS
let paragraphes = document.querySelectorAll(".texte");
console.log(paragraphes.length); // 3

paragraphes.forEach(p => {
  console.log(p.textContent); // "Un", "Deux", "Trois"
});
Console
3
Un
Deux
Trois
📖 NodeList vs HTMLCollection
NodeListRetournee par querySelectorAll — possede .forEach()
HTMLCollectionRetournee par getElementsByClassName — pas de .forEach()
Live ou statique ?HTMLCollection est live (se met a jour). NodeList de querySelectorAll est statique.
⚠ Pas de forEach sur HTMLCollection

Si tu utilises getElementsByClassName ou getElementsByTagName, le resultat est une HTMLCollection qui n a pas de methode .forEach(). Convertis-la en tableau :

JS
let elements = document.getElementsByClassName("texte");
Array.from(elements).forEach(el => {
  console.log(el.textContent);
});
🌐 Exemple concret

Selectionner tous les boutons d un menu pour leur attacher un ecouteur :

JS
let boutons = document.querySelectorAll(".menu button");

boutons.forEach(bouton => {
  bouton.addEventListener("click", () => {
    console.log("Clique sur :", bouton.textContent);
  });
});

JS · Fiche Originale

Fiche 217 — Modifier le contenu
💡 En clair

Une fois l element selectionne, on peut changer son contenu avec textContent (texte brut) ou innerHTML (HTML interprete).

📖 Proprietes principales
textContentTexte brut — HTML non interprete · recommande pour du texte
innerHTMLHTML — interprete les balises · prudent (faille XSS)
innerTextTexte visible — tient compte du style (CSS)

Exemple — textContent (texte brut) :

HTML
<h1 id="titre">Bonjour</h1>
JS
let titre = document.getElementById("titre");
titre.textContent = "Salut tout le monde";
// <h1>Salut tout le monde</h1>

Exemple — innerHTML (HTML interprete) :

JS
let div = document.querySelector("div");
div.innerHTML = "<strong>Texte en gras</strong>";
// <div><strong>Texte en gras</strong></div>
⚠ Faille XSS

innerHTML interprete le HTML. Si tu y mets du contenu provenant de l utilisateur, c est une faille XSS (injection de code).

Pour du texte utilisateur, utilise toujours textContent ou element.append(document.createTextNode(texte)).

Difference visible :

JS
element.textContent = "<strong>Gras</strong>";
// Affiche litteralement : <strong>Gras</strong>

element.innerHTML = "<strong>Gras</strong>";
// Affiche : Gras (en gras)
🌐 Exemple concret — compteur de clics

Un compteur qui se met a jour sans recharger la page :

HTML
<p>Nombre de clics : <span id="compteur">0</span></p>
<button id="btn">Cliquer</button>
JS
let compteur = 0;
let affichage = document.getElementById("compteur");
let bouton = document.getElementById("btn");

bouton.addEventListener("click", () => {
  compteur++;
  affichage.textContent = compteur;
});

Chaque clic met a jour le texte sans recharger la page.

JS · Fiche Originale

Fiche 218 — Modifier les attributs
💡 En clair

On peut lire, modifier, ajouter ou supprimer les attributs HTML d un element (src, href, id, value, disabled...).

📖 Methodes principales
getAttribute(nom)Lire un attribut
setAttribute(nom, valeur)Modifier / ajouter
removeAttribute(nom)Supprimer
hasAttribute(nom)Verifier l existence
✏ Syntaxe generale

JS
element.getAttribute("src")
element.setAttribute("src", "image.jpg")
element.removeAttribute("disabled")

Exemple — getAttribute :

HTML
<a id="lien" href="https://exemple.com">Lien</a>
JS
let lien = document.getElementById("lien");
console.log(lien.getAttribute("href")); // "https://exemple.com"

Exemple — setAttribute :

JS
lien.setAttribute("href", "https://google.com");
lien.setAttribute("target", "_blank");

Exemple — changer une image :

HTML
<img id="photo" src="photo1.jpg" alt="Photo">
JS
let photo = document.getElementById("photo");
photo.setAttribute("src", "photo2.jpg");
💡 Acces direct aux attributs courants

Certains attributs sont accessibles directement comme des proprietes (plus court et plus lisible) :

JS
image.src = "photo2.jpg";
lien.href = "https://google.com";
input.value = "Nouveau texte";
input.disabled = true;
caseACocher.checked = true;
🌐 Exemple concret

Un bouton qui active / desactive un champ :

HTML
<input id="nom" disabled>
<button id="btn">Activer</button>
JS
let input = document.getElementById("nom");
let bouton = document.getElementById("btn");

bouton.addEventListener("click", () => {
  input.disabled = !input.disabled;
});

JS · Fiche Originale

Fiche 219 — Modifier les classes CSS
💡 En clair

On peut ajouter, supprimer ou basculer des classes CSS d un element pour changer son style dynamiquement via l objet classList.

📖 Methodes de classList
add("classe")Ajouter une classe
remove("classe")Supprimer une classe
toggle("classe")Ajouter si absente, supprimer si presente
contains("classe")Verifier la presence
replace("old", "new")Remplacer une classe
✏ Syntaxe generale

JS
element.classList.add("active")
element.classList.remove("active")
element.classList.toggle("active")
element.classList.contains("active")

Exemple — add / remove :

HTML
<div id="boite">Contenu</div>
CSS
.rouge { background: red; }
.bleu { background: blue; }
JS
let boite = document.getElementById("boite");

boite.classList.add("rouge");       // ajoute la classe
boite.classList.remove("rouge");    // enleve la classe
boite.classList.add("bleu");        // ajoute une autre
💡 toggle — le plus pratique

toggle ajoute la classe si elle n existe pas, la retire si elle existe. Parfait pour les modes on/off :

JS
boite.classList.toggle("active");

Exemple — contains (verifier la presence) :

JS
if (boite.classList.contains("rouge")) {
  console.log("La boite est rouge");
}
🌐 Exemple concret — mode sombre

Chaque clic active ou desactive le mode sombre sur toute la page. C est exactement comme ca que fonctionnent la plupart des sites :

HTML
<button id="btnTheme">Changer le theme</button>
CSS
.dark {
  background: black;
  color: white;
}
JS
let bouton = document.getElementById("btnTheme");

bouton.addEventListener("click", () => {
  document.body.classList.toggle("dark");
});

JS · Fiche Originale

Fiche 220 — Creer un element
💡 En clair

On peut creer un nouvel element HTML en JavaScript avec document.createElement(), sans qu il existe dans le HTML de depart.

L element cree existe en memoire, mais n est pas encore dans la page. Il faut l ajouter (voir fiche 221).

✏ Syntaxe generale

document.createElement("nomBalise") — retourne un nouvel element vide.

JS
let nouveau = document.createElement("p");
nouveau.textContent = "Je suis un nouveau paragraphe";

A ce stade, l element existe en memoire mais n est pas encore dans la page.

Creer differents types d elements :

JS
let div = document.createElement("div");
let lien = document.createElement("a");
let image = document.createElement("img");
let bouton = document.createElement("button");
let liste = document.createElement("ul");
let item = document.createElement("li");
💡 Configurer l element avant de l ajouter

On peut configurer l element (texte, attributs, classes) avant de l ajouter dans la page — c est plus performant :

JS
let lien = document.createElement("a");
lien.textContent = "Visiter Google";
lien.href = "https://google.com";
lien.target = "_blank";
lien.classList.add("bouton");
🌐 Exemple concret — site de taches

Une fonction qui cree une nouvelle ligne pour chaque tache ajoutee :

JS
function creerTache(texte) {
  let li = document.createElement("li");
  li.textContent = texte;
  li.classList.add("tache");
  return li;
}

Chaque appel cree un nouvel element <li> pret a etre insere dans la liste.

JS · Fiche Originale

Fiche 221 — Ajouter un element
💡 En clair

Une fois l element cree, il faut l inserer dans le DOM pour qu il apparaisse a l ecran.

📖 Methodes principales
appendChild(element)Ajoute a la fin d un parent
append(element)Ajoute a la fin (accepte plusieurs + texte)
prepend(element)Ajoute au debut
insertBefore(nouveau, existant)Insere avant un element
after(element)Insere juste apres un element
before(element)Insere juste avant un element
✏ Syntaxe generale

JS
parent.appendChild(nouveau)
parent.append(nouveau)
parent.prepend(nouveau)
parent.insertBefore(nouveau, existant)

Exemple — appendChild :

HTML
<ul id="liste"></ul>
JS
let liste = document.getElementById("liste");
let item = document.createElement("li");
item.textContent = "Nouvelle tache";

liste.appendChild(item);

Resultat :

HTML
<ul id="liste">
  <li>Nouvelle tache</li>
</ul>

Exemple — prepend (au debut) :

JS
liste.prepend(item);

L element est ajoute en premier dans la liste.

Exemple — insertBefore :

JS
parent.insertBefore(nouveau, existant);

Insere nouveau avant existant.

🌐 Exemple concret — ajouter une tache

Chaque clic ajoute une nouvelle ligne a la liste, en direct :

HTML
<input id="champ" placeholder="Nouvelle tache">
<button id="btn">Ajouter</button>
<ul id="liste"></ul>
JS
let champ = document.getElementById("champ");
let bouton = document.getElementById("btn");
let liste = document.getElementById("liste");

bouton.addEventListener("click", () => {
  if (champ.value.trim() === "") return;

  let li = document.createElement("li");
  li.textContent = champ.value;
  liste.appendChild(li);

  champ.value = ""; // vider le champ
});

JS · Fiche Originale

Fiche 222 — Supprimer un element
💡 En clair

On peut retirer un element du DOM avec remove() (moderne) ou removeChild() (ancien).

📖 Methodes principales
remove()Supprime l element directement (moderne)
parent.removeChild(element)Supprime un enfant depuis son parent (ancien)
✏ Syntaxe generale

JS
element.remove()
parent.removeChild(element)

Exemple — remove() :

HTML
<p id="texte">A supprimer</p>
JS
let texte = document.getElementById("texte");
texte.remove();

L element disparait de la page.

Exemple — removeChild() :

JS
let parent = document.getElementById("liste");
let enfant = parent.firstElementChild;
parent.removeChild(enfant);

Supprime le premier enfant de la liste.

💡 Astuce rapide — tout vider

Pour supprimer tous les enfants d un element :

JS
let liste = document.getElementById("liste");
liste.innerHTML = ""; // vide tout
🌐 Exemple concret — liste de taches avec suppression

Chaque tache a son bouton de suppression. Un clic retire la tache de la page :

JS
let liste = document.getElementById("liste");

function ajouterTache(texte) {
  let li = document.createElement("li");
  li.textContent = texte;

  let bouton = document.createElement("button");
  bouton.textContent = "X";

  bouton.addEventListener("click", () => {
    li.remove(); // supprime la tache
  });

  li.appendChild(bouton);
  liste.appendChild(li);
}

JS · Fiche Originale

Fiche 223 — Evenements
💡 En clair

Un evenement est une action qui se produit dans la page : clic, saisie clavier, survol, chargement, soumission de formulaire...

JavaScript peut ecouter ces evenements et reagir quand ils se produisent.

📖 Evenements les plus courants
clickOn clique
dblclickOn double-clique
inputOn tape dans un champ
changeUn champ change de valeur
submitUn formulaire est envoye
keydown / keyupTouche enfoncee / relachee
mouseover / mouseoutSouris entre / sort
loadLa page est chargee
scrollOn fait defiler
✏ Syntaxe generale

element.addEventListener("type", fonction) — la fonction est appelee quand l evenement se produit.

JS
element.addEventListener("click", fonction);

Exemple simple :

HTML
<button id="btn">Cliquer</button>
JS
let bouton = document.getElementById("btn");

bouton.addEventListener("click", () => {
  console.log("Clique !");
});

Exemple — plusieurs evenements :

JS
input.addEventListener("input", () => {
  console.log("En train de taper...");
});

input.addEventListener("change", () => {
  console.log("Valeur changee");
});
🌐 Exemple concret

Un bouton qui change le texte d un titre au clic :

HTML
<h1 id="titre">Bonjour</h1>
<button id="btn">Changer</button>
JS
let titre = document.getElementById("titre");
let bouton = document.getElementById("btn");

bouton.addEventListener("click", () => {
  titre.textContent = "Texte change !";
});

JS · Fiche Originale

Fiche 224 — addEventListener()
💡 En clair

addEventListener() est la methode moderne pour ecouter un evenement sur un element.

✏ Syntaxe generale

element.addEventListener(type, fonction)

element.addEventListener(type, fonction, options)

type : nom de l evenement ("click", "input"...).

fonction : fonction appelee quand l evenement se produit.

options : objet optionnel (once, capture, passive).

JS
element.addEventListener(type, fonction)
element.addEventListener(type, fonction, options)

Exemple simple :

JS
bouton.addEventListener("click", () => {
  console.log("Clique");
});

Avec une fonction nommee :

JS
function saluer() {
  console.log("Bonjour");
}

bouton.addEventListener("click", saluer);
⚠ Pas de parentheses apres le nom de fonction

addEventListener("click", saluer) — on passe la fonction, on ne l appelle pas.

addEventListener("click", saluer()) — FAUX : la fonction est appelee immediatement, et c est son resultat (souvent undefined) qui est enregistre.

💡 Plusieurs ecouteurs sur le meme element

On peut attacher plusieurs ecouteurs au meme element. Ils s executent tous, dans l ordre :

JS
bouton.addEventListener("click", () => console.log("Premier"));
bouton.addEventListener("click", () => console.log("Deuxieme"));
🔄 Supprimer un ecouteur

removeEventListener(type, fonction) — necessite une fonction nommee. Une fonction anonyme ne peut pas etre retiree.

JS
function gererClic() {
  console.log("Clique");
}

bouton.addEventListener("click", gererClic);
bouton.removeEventListener("click", gererClic);
💡 Option once

Pour qu un ecouteur s execute une seule fois puis se retire automatiquement :

JS
bouton.addEventListener("click", () => {
  console.log("Une seule fois");
}, { once: true });
🌐 Exemple concret

Un champ de recherche qui declenche une action quand on appuie sur Entree :

JS
input.addEventListener("keydown", (event) => {
  if (event.key === "Enter") {
    rechercher(input.value);
  }
});

JS · Fiche Originale

Fiche 225 — Objet evenement
💡 En clair

Quand un evenement se declenche, JavaScript passe automatiquement un objet evenement a la fonction.

Cet objet contient toutes les infos sur ce qui s est passe.

✏ Syntaxe generale

element.addEventListener("click", (event) => { ... }) — l objet event est passe en parametre.

JS
element.addEventListener("click", (event) => {
  console.log(event);
});
📖 Proprietes courantes
event.targetL element qui a declenche l evenement
event.typeType d evenement ("click"...)
event.keyTouche pressee (clavier)
event.clientX / clientYPosition de la souris
event.preventDefault()Empeche le comportement par defaut
event.stopPropagation()Stoppe la propagation

Exemple — event.target :

JS
bouton.addEventListener("click", (event) => {
  console.log(event.target);              // <button>...</button>
  console.log(event.target.textContent); // "Cliquer"
});

event.target est l element qui a recu l evenement. Tres utile pour la delegation d evenements (un seul ecouteur sur le parent, voir quel enfant a ete clique).

Exemple — event.key (clavier) :

JS
document.addEventListener("keydown", (event) => {
  console.log("Touche pressee :", event.key);
});
Console
Touche pressee : a
Touche pressee : Enter
Touche pressee : Escape

Exemple — event.preventDefault() (empecher le comportement par defaut) :

JS
lien.addEventListener("click", (event) => {
  event.preventDefault(); // empeche la navigation
  console.log("Lien bloque");
});

Tres utile pour empecher l envoi d un formulaire ou la navigation d un lien.

Exemple — coordonnees souris :

JS
document.addEventListener("click", (event) => {
  console.log(`Clic a (${event.clientX}, ${event.clientY})`);
});
🌐 Exemple concret — delegation d evenements

Un seul ecouteur sur le parent, mais on sait quel bouton a ete clique via event.target. Cette technique s appelle la delegation d evenements :

HTML
<div id="boutons">
  <button data-action="ajouter">Ajouter</button>
  <button data-action="supprimer">Supprimer</button>
  <button data-action="modifier">Modifier</button>
</div>
JS
let conteneur = document.getElementById("boutons");

conteneur.addEventListener("click", (event) => {
  if (event.target.tagName === "BUTTON") {
    console.log("Action :", event.target.dataset.action);
  }
});

JS · Fiche Originale

Fiche 226 — Formulaires
💡 En clair

Un formulaire HTML permet a l utilisateur de saisir des donnees. JavaScript peut lire ces donnees, les valider, et les envoyer au serveur.

Structure HTML de base :

HTML
<form id="monFormulaire">
  <label for="nom">Nom :</label>
  <input type="text" id="nom" name="nom">

  <label for="email">Email :</label>
  <input type="email" id="email" name="email">

  <button type="submit">Envoyer</button>
</form>
✏ Recuperer les valeurs

On utilise la propriete .value sur chaque champ :

JS
let nom = document.getElementById("nom").value;
let email = document.getElementById("email").value;
let age = document.getElementById("age").value;
✏ Ecouter la soumission

On intercepte l evenement submit sur le formulaire :

JS
let formulaire = document.getElementById("monFormulaire");

formulaire.addEventListener("submit", (event) => {
  event.preventDefault(); // empeche le rechargement de la page

  let nom = document.getElementById("nom").value;
  let email = document.getElementById("email").value;

  console.log("Nom :", nom);
  console.log("Email :", email);
});
⚠ event.preventDefault() est indispensable

Sans preventDefault(), la page se recharge et le JavaScript n a pas le temps de s executer. C est l erreur la plus courante avec les formulaires.

📖 Types de champs et recuperation
<input type="text/email/password/number">element.value
<textarea>element.value
<select>element.value
<input type="checkbox">element.checked (bool)
<input type="radio">document.querySelector('input[name="sexe"]:checked').value
🌐 Exemple concret — formulaire d inscription

Un formulaire qui affiche les donnees saisies :

HTML
<form id="inscription">
  <input type="text" id="pseudo" placeholder="Pseudo">
  <input type="email" id="mail" placeholder="Email">
  <button type="submit">S'inscrire</button>
</form>
<p id="resultat"></p>
JS
let form = document.getElementById("inscription");
let resultat = document.getElementById("resultat");

form.addEventListener("submit", (event) => {
  event.preventDefault();

  let pseudo = document.getElementById("pseudo").value;
  let mail = document.getElementById("mail").value;

  resultat.textContent = `Bienvenue ${pseudo} (${mail})`;
  form.reset(); // vide le formulaire
});

JS · Fiche Originale

Fiche 227 — Validation cote navigateur
💡 En clair

La validation cote navigateur consiste a verifier les donnees saisies dans un formulaire avant de les envoyer au serveur.

C est la premiere ligne de defense. Le serveur doit toujours revalider ensuite (la validation cote client peut etre contournee).

✏ Attributs HTML de validation

Le navigateur affiche automatiquement un message si la regle n est pas respectee :

HTML
<input type="email" required>               <!-- email valide + obligatoire -->
<input type="text" minlength="3">         <!-- au moins 3 caracteres -->
<input type="text" maxlength="20">        <!-- au plus 20 caracteres -->
<input type="number" min="1" max="100">   <!-- entre 1 et 100 -->
<input type="text" pattern="[0-9]{5}">      <!-- 5 chiffres (code postal) -->
✏ Verifier dans le JavaScript

checkValidity() retourne true ou false selon que le champ respecte les regles HTML :

JS
let input = document.getElementById("nom");

if (input.value.trim() === "") {
  console.log("Le champ est vide");
}

if (!input.checkValidity()) {
  console.log("Champ invalide");
}

Exemple — validation manuelle :

JS
form.addEventListener("submit", (event) => {
  event.preventDefault();

  let pseudo = document.getElementById("pseudo").value.trim();
  let email = document.getElementById("mail").value.trim();
  let erreurs = [];

  if (pseudo.length < 3) {
    erreurs.push("Le pseudo doit faire au moins 3 caracteres");
  }

  if (!email.includes("@")) {
    erreurs.push("Email invalide");
  }

  if (erreurs.length > 0) {
    afficherErreurs(erreurs);
    return;
  }

  envoyerDonnees({ pseudo, email });
});
✏ Afficher les erreurs a l utilisateur

On construit un message d erreur pour chaque probleme detecte :

JS
function afficherErreurs(erreurs) {
  let zone = document.getElementById("erreurs");
  zone.innerHTML = "";
  erreurs.forEach(msg => {
    let p = document.createElement("p");
    p.textContent = msg;
    p.classList.add("erreur");
    zone.appendChild(p);
  });
}
🌐 Exemple concret

Un formulaire d inscription qui refuse les emails sans @ avant d envoyer au serveur. L utilisateur recoit un message immediat, sans attendre la reponse du serveur.

JS · Fiche Originale

Fiche 228 — localStorage
💡 En clair

localStorage permet de stocker des donnees dans le navigateur de facon permanente.

Les donnees restent meme apres : un rechargement de la page, la fermeture du navigateur, l extinction de l ordinateur.

✏ Syntaxe generale

JS
localStorage.setItem("cle", "valeur")    // enregistrer
localStorage.getItem("cle")             // lire (retourne null si inexistante)
localStorage.removeItem("cle")          // supprimer une cle
localStorage.clear()                   // tout vider

Exemple simple :

JS
// Enregistrer
localStorage.setItem("nom", "Awa");

// Lire
let nom = localStorage.getItem("nom");
console.log(nom); // "Awa"

// Supprimer une cle
localStorage.removeItem("nom");

// Tout vider
localStorage.clear();
⚠ Stocker un objet — JSON obligatoire

localStorage ne stocke que des chaines de caracteres. Pour un objet ou un tableau, il faut JSON.stringify() et JSON.parse() :

JS
let user = { nom: "Awa", age: 25 };

// Enregistrer
localStorage.setItem("user", JSON.stringify(user));

// Lire
let userRecupere = JSON.parse(localStorage.getItem("user"));
console.log(userRecupere.nom); // "Awa"
🌐 Exemple concret — mode sombre persistant

Si l utilisateur active le mode sombre, il le retrouve au prochain chargement :

JS
let bouton = document.getElementById("btnTheme");

// Au chargement, appliquer le theme sauvegarde
if (localStorage.getItem("theme") === "dark") {
  document.body.classList.add("dark");
}

// Au clic, basculer et sauvegarder
bouton.addEventListener("click", () => {
  document.body.classList.toggle("dark");

  let theme = document.body.classList.contains("dark") ? "dark" : "light";
  localStorage.setItem("theme", theme);
});
🌐 Exemple concret — liste de taches persistante

Sauvegarder une liste de taches pour la retrouver au prochain chargement :

JS
function sauvegarderTaches(taches) {
  localStorage.setItem("taches", JSON.stringify(taches));
}

function chargerTaches() {
  let data = localStorage.getItem("taches");
  return data ? JSON.parse(data) : [];
}

JS · Fiche Originale

Fiche 229 — sessionStorage
💡 En clair

sessionStorage fonctionne exactement comme localStorage, mais les donnees ne durent que le temps de la session (onglet ouvert).

Des que l utilisateur ferme l onglet, les donnees sont effacees.

✏ Syntaxe generale (meme API que localStorage)

JS
sessionStorage.setItem("cle", "valeur")
sessionStorage.getItem("cle")
sessionStorage.removeItem("cle")
sessionStorage.clear()
📖 Comparaison localStorage vs sessionStorage
DureelocalStorage : permanent · sessionStorage : jusqu'a fermeture de l onglet
Partage entre ongletslocalStorage : oui · sessionStorage : non (propre a chaque onglet)
Capacite~5-10 Mo pour les deux
APIIdentique : setItem / getItem / removeItem / clear

Exemple simple :

JS
sessionStorage.setItem("etape", "2");

let etape = sessionStorage.getItem("etape");
console.log(etape); // "2"

Si l utilisateur ferme l onglet et rouvre la page, etape n existe plus.

🌐 Exemple concret — formulaire multi-etapes

Un formulaire en 3 etapes (infos perso → adresse → paiement). On stocke les donnees dans sessionStorage pour les retrouver entre les etapes, mais elles disparaissent quand l utilisateur ferme l onglet :

JS
// Etape 1
sessionStorage.setItem("etape1", JSON.stringify({ nom, email }));

// Etape 2 (autre page)
let etape1 = JSON.parse(sessionStorage.getItem("etape1"));
console.log(etape1.nom);
🌐 Exemple concret — jeton temporaire

Un site qui stocke un token temporaire apres une connexion, et le supprime des que l utilisateur ferme l onglet (plus sur) :

JS
sessionStorage.setItem("token", "abc123");

// A l utilisation
let token = sessionStorage.getItem("token");
💡 Quand utiliser l un ou l autre ?

localStorage → preferences utilisateur, theme, panier d achat, taches

sessionStorage → donnees temporaires, jetons, formulaires multi-etapes

23
Chapitre 2320 fiches

HTTP, APIs et Fetch

Communiquer avec des services web

JS · Fiche Originale

Fiche 230 — HTTP : dialogue client-serveur
💡 En clair

HTTP signifie HyperText Transfer Protocol. C'est le langage que les navigateurs (le client) et les serveurs utilisent pour communiquer. Chaque fois que tu ouvres un site, ton navigateur envoie une requête HTTP au serveur, qui renvoie une réponse HTTP.

JS
// Le dialogue HTTP
// Navigateur  ---- requête HTTP ---->  Serveur
// Navigateur  <---- réponse HTTP ----  Serveur
//
// Le client demande, le serveur répond. Toujours dans ce sens :
// le serveur ne prend jamais l'initiative.

Étapes concrètes quand tu ouvres une page :

JS
// 1. Le navigateur envoie une requête HTTP GET / vers exemple.com
// 2. Le serveur reçoit, prépare la page HTML
// 3. Le serveur renvoie une réponse HTTP avec le HTML
// 4. Le navigateur affiche la page
//
// Chaque image, CSS, script = une nouvelle requête HTTP
✏️ Ligne par ligne
Navigateur ---- requête HTTP ----> Serveurle client demande une ressource.
Navigateur <---- réponse HTTP ---- Serveurle serveur renvoie la ressource ou une erreur.
chaque fichier = une requêteHTML, CSS, JS, images, fonts...

JavaScript peut lui-même lancer des requêtes HTTP via fetch() — sans recharger la page :

JS
// Exemple : récupérer des utilisateurs depuis une API
fetch("https://api.exemple.com/users")
  .then(response => response.json())
  .then(users => console.log(users));

// Permet à une appli d'aller chercher des données
// en arrière-plan et de mettre à jour l'interface.
📖 Mots à connaître
HTTPprotocole de dialogue client/serveur du web.
requêtemessage envoyé par le client au serveur — voir fiche 231A.
réponsemessage renvoyé par le serveur — voir fiche 232A.
fetch()fonction JavaScript moderne pour lancer une requête HTTP — voir fiche 237A.
⚠️ Pièges fréquents
  • Le serveur ne peut pas envoyer d'information sans demande préalable du client — c'est la raison d'être des websockets pour le temps réel.
  • Une requête HTTP peut échouer (réseau coupé, serveur down, URL invalide) — toujours prévoir un .catch() avec fetch.
💡 Astuce

Rappel : voir la fiche 231A sur la structure d'une requête, la fiche 232A sur la structure d'une réponse, et le chapitre 18 sur fetch().

JS · Fiche Originale

Fiche 231a — Requete HTTP : structure
💡 En clair

Une requête HTTP est composée de 4 éléments : la méthode (GET, POST...), l'URL (/users/1), les headers (infos annexes) et le body (données envoyées, optionnel). Comprendre cette structure est essentiel pour utiliser fetch() correctement.

JS
// Structure d'une requête HTTP
// GET /users/1 HTTP/1.1
// Host: api.exemple.com
// Accept: application/json
// Authorization: Bearer abc123
//
// { "nom": "Awa" }    <-- body (optionnel, pour POST)
✏️ Ligne par ligne
GET /users/1 HTTP/1.1la ligne de requête : méthode + URL + version HTTP.
Host: api.exemple.comun header — indique le domaine cible.
Accept: application/jsonun header — indique le format attendu en réponse.
{ "nom": "Awa" }le body — optionnel, présent surtout avec POST.

Les 4 éléments dans fetch() :

JS
fetch("https://api.exemple.com/users", {
  method: "POST",                           // 1. méthode
  headers: {                                 // 2. headers
    "Content-Type": "application/json",
    "Authorization": "Bearer abc123"
  },
  body: JSON.stringify({ nom: "Awa" })       // 3. body
});
// L'URL est le 1er argument : https://api.exemple.com/users
📖 Mots à connaître
méthodel'action : GET (lire), POST (créer), PUT (remplacer), PATCH (modifier), DELETE (supprimer). Voir fiche 231B.
URLl'adresse de la ressource visée — voir fiche 231B.
headersinfos annexes : Content-Type, Authorization, Accept...
bodydonnées envoyées (JSON, FormData...) — optionnel, surtout pour POST/PUT/PATCH.
⚠️ Pièges fréquents
  • GET n'envoie normalement pas de body — les données vont dans l'URL (query string). Pour envoyer un body, utiliser POST, PUT ou PATCH.
  • Le Content-Type doit correspondre au format réel du body : application/json pour du JSON, application/x-www-form-urlencoded pour un formulaire classique.
💡 Astuce

Rappel : voir la fiche 231B sur les méthodes HTTP, la fiche 232A sur la réponse, et le chapitre 18 sur fetch().

JS · Fiche Originale

Fiche 231b — Requete HTTP : methodes
💡 En clair

Les méthodes HTTP indiquent l'intention de la requête : lire, créer, modifier ou supprimer. Choisir la bonne méthode est crucial pour respecter les conventions REST et construire des API prévisibles.

JS
// Les 5 méthodes principales
// GET    → Récupérer des données
// POST   → Créer une nouvelle ressource
// PUT    → Remplacer entièrement une ressource
// PATCH  → Modifier partiellement une ressource
// DELETE → Supprimer une ressource

Une même URL, des intentions différentes :

JS
GET    /users/1     // lire l'utilisateur 1
POST   /users      // créer un nouvel utilisateur
PUT    /users/1     // remplacer entièrement l'utilisateur 1
PATCH  /users/1     // modifier un champ de l'utilisateur 1
DELETE /users/1     // supprimer l'utilisateur 1
✏️ Ligne par ligne
GET /users/1lire — sans body, sans effet de bord (idempotent).
POST /userscréer — body contient les données, génère un nouvel ID.
PUT /users/1remplacer — body contient TOUTES les données.
PATCH /users/1modifier — body contient seulement les champs à changer.
DELETE /users/1supprimer — généralement sans body.

Utilisation dans fetch() :

JS
// GET (par défaut, pas de méthode à préciser)
fetch("/users");

// POST avec body JSON
fetch("/users", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ nom: "Awa" })
});

// DELETE
fetch("/users/1", { method: "DELETE" });
📖 Mots à connaître
GETrécupère — sans body, idempotent.
POSTcrée — body contient les données de la nouvelle ressource.
PUTremplace — body contient la version complète. Idempotent.
PATCHmodifie partiellement — body contient seulement les champs à changer.
DELETEsupprime — généralement sans body. Idempotent.
⚠️ Pièges fréquents
  • Confondre PUT et PATCH est fréquent : PUT remplace tout (les champs non fournis sont effacés), PATCH ne modifie que les champs fournis.
  • GET ne doit jamais modifier de données côté serveur — sinon on perd l'idempotence et la compatibilité avec le cache navigateur.
💡 Astuce

Rappel : voir la fiche 231A sur la structure d'une requête, la fiche 235 sur REST, et le chapitre 18 sur fetch().

JS · Fiche Originale

Fiche 232a — Reponse HTTP : structure
💡 En clair

Une réponse HTTP est le message renvoyé par le serveur. Elle est composée de 3 éléments : le code de statut (200, 404, 500...), les headers (infos sur la réponse) et le body (les données renvoyées — souvent du JSON).

JS
// Structure d'une réponse HTTP
// HTTP/1.1 200 OK
// Content-Type: application/json
// Date: Mon, 24 Sep 2026 10:00:00 GMT
//
// { "id": 1, "nom": "Awa", "age": 25 }    <-- body
✏️ Ligne par ligne
HTTP/1.1 200 OKla ligne de statut : version HTTP + code + message.
Content-Type: application/jsonun header — indique le format du body.
Date: ...un header — date de génération de la réponse.
{ "id": 1, ... }le body — les données, souvent en JSON.

Accès aux éléments dans fetch() :

JS
fetch("https://api.exemple.com/users/1")
  .then(response => {
    console.log(response.status);      // 200 (code HTTP)
    console.log(response.ok);           // true si 200-299
    console.log(response.headers.get("Content-Type"));
    return response.json();            // parser le body JSON
  })
  .then(data => console.log(data));    // { id: 1, nom: "Awa", ... }
Console
200
true
application/json
{ id: 1, nom: 'Awa', age: 25 }
✏️ Ligne par ligne
response.statusle code HTTP numérique : 200, 404, 500...
response.okraccourci : true si le code est entre 200 et 299.
response.headers.get("Content-Type")accède à un header spécifique.
response.json()parse le body JSON en objet JS — voir fiche 238.

Codes HTTP essentiels :

JS
// 2xx = succès
//   200 OK                 → requête réussie
//   201 Created            → ressource créée (POST réussi)
//   204 No Content         → succès sans body (DELETE)
// 3xx = redirection
//   301 Moved Permanently  → URL changée définitivement
// 4xx = erreur du client
//   400 Bad Request        → requête mal formée
//   401 Unauthorized       → non authentifié
//   403 Forbidden           → authentifié mais non autorisé
//   404 Not Found          → ressource introuvable
// 5xx = erreur du serveur
//   500 Internal Server Error → bug serveur
📖 Mots à connaître
code de statutnombre à 3 chiffres indiquant le résultat (200, 404...).
headersinfos annexes sur la réponse : Content-Type, Date, Content-Length...
bodyles données renvoyées — JSON, HTML, image, texte...
response.okraccourci pour vérifier que le code est 2xx.
⚠️ Pièges fréquents
  • fetch() ne rejette PAS la Promise sur une erreur HTTP (404, 500) — il faut vérifier response.ok manuellement. Voir la fiche 237B.
  • Le body ne peut être lu qu'une seule fois — appeler deux fois response.json() échoue. Le stocker dans une variable si on en a besoin plusieurs fois.
💡 Astuce

Rappel : voir la fiche 231A sur la requête, la fiche 238 sur response.json(), et le chapitre 18 sur fetch().

JS · Fiche Originale

Fiche 232b — Reponse HTTP : statuts
💡 En clair

Les codes HTTP sont des nombres a 3 chiffres qui indiquent le resultat d une requete. Ils sont ranges en 5 familles.

📖 Les 5 familles
1xxInformation
2xxSucces
3xxRedirection
4xxErreur du client (ton navigateur)
5xxErreur du serveur
📖 Les codes a connaitre
200OK — succes classique
201Created — ressource creee (apres POST)
204No Content — succes sans contenu (souvent DELETE)
400Bad Request — requete mal formee
401Unauthorized — non authentifie
403Forbidden — authentifie mais non autorise
404Not Found — ressource introuvable
500Internal Server Error — bug du serveur
503Service Unavailable — serveur en maintenance

En JavaScript, on les verifie via response.status ou response.ok :

JS
fetch(url).then(response => {
  if (response.status === 200) {
    console.log("Succes");
  } else if (response.status === 404) {
    console.log("Introuvable");
  } else if (response.status >= 500) {
    console.log("Erreur serveur");
  }
});

JS · Fiche Originale

Fiche 233 — Methodes HTTP
💡 En clair

Les methodes HTTP definissent l action sur une ressource. Avec fetch(), on les precise via method dans les options.

📖 CRUD complet
CreatePOST /users — creer un utilisateur
ReadGET /users — lister · GET /users/1 — lire un
Update (remplacer)PUT /users/1 — remplace tous les champs
Update (partiel)PATCH /users/1 — modifie un champ precis
DeleteDELETE /users/1 — supprime

PUT vs PATCH — la difference importante :

JS
// PUT : tous les champs doivent etre fournis
fetch("/users/1", {
  method: "PUT",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ nom: "Awa", age: 26, ville: "Dakar" })
});

// PATCH : on ne modifie qu un champ
fetch("/users/1", {
  method: "PATCH",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ age: 26 })
});
🌐 Exemple concret

PUT → utilise quand on enregistre tout le profil d un coup (formulaire complet).

PATCH → utilise quand on change juste l avatar ou la bio (modification rapide).

JS · Fiche Originale

Fiche 234 — API : role et fonctionnement
💡 En clair

API signifie Application Programming Interface. C est un ensemble de regles qui permet a deux programmes de communiquer.

Une API web, c est un serveur qui expose des URL pour recuperer ou envoyer des donnees.

🧮 Image mentale

Une API, c est comme un serveur au restaurant :

Tu (le client) ne vas pas en cuisine. Tu passes commande au serveur (l API). Le serveur apporte ton plat (les donnees).

Tu n as pas besoin de savoir comment la cuisine fonctionne. Tu utilises juste l interface.

Exemple d URL d API :

HTTP
https://api.exemple.com/users
https://api.exemple.com/users/1
https://api.exemple.com/posts

Chaque URL correspond a une ressource.

Ce qu une API renvoie — le plus souvent du JSON :

JSON
{
  "id": 1,
  "nom": "Awa",
  "email": "awa@mail.com"
}
📖 Pourquoi c est utile
SeparationFrontend (site) et backend (serveur) independants
ReutilisableLes memes donnees pour plusieurs applis (web, mobile)
ControleLimite ce que chaque client peut voir ou faire
🌐 Exemples d API connues

API meteo : OpenWeatherMap, Meteo France. API de paiement : Stripe, PayPal. API de cartes : Google Maps. API reseaux sociaux : Twitter, GitHub, YouTube.

JS · Fiche Originale

Fiche 235 — REST : ressources et endpoints
💡 En clair

REST (Representational State Transfer) est un style d'architecture pour construire des API. Une API REST organise les échanges autour de ressources (identifiées par des URL) et utilise les méthodes HTTP (GET, POST, PUT, DELETE) pour agir dessus. C'est le standard de fait du web.

Les 5 opérations CRUD sur une ressource /articles :

JS
GET    /articles          // liste des articles (Read all)
GET    /articles/5        // un seul article (Read one)
POST   /articles          // créer un article (Create)
PUT    /articles/5        // remplacer l'article 5 (Update full)
PATCH  /articles/5        // modifier partiellement (Update partial)
DELETE /articles/5        // supprimer l'article 5 (Delete)
✏️ Ligne par ligne
GET /articleslister toutes les ressources — collection au pluriel.
GET /articles/5accéder à une ressource précise via son ID.
POST /articlescréer — body contient les données de la nouvelle ressource.
PUT /articles/5remplacer entièrement la ressource 5.
DELETE /articles/5supprimer la ressource 5.

Bonnes pratiques REST :

JS
// ✅ URL au pluriel
GET /users         (pas /user)
GET /articles      (pas /article)

// ✅ Pas de verbe dans l'URL — le verbe = la méthode HTTP
GET    /users/1          (pas /getUser?id=1)
POST   /users            (pas /createUser)
DELETE /users/1          (pas /deleteUser?id=1)

// ✅ Ressources imbriquées
GET /users/1/articles    // articles de l'utilisateur 1
GET /users/1/articles/3   // article 3 de l'utilisateur 1
📖 Mots à connaître
RESTstyle d'architecture pour les API basé sur ressources + méthodes HTTP.
CRUDCreate, Read, Update, Delete — les 4 opérations de base.
endpointune combinaison URL + méthode HTTP (ex. GET /users/1).
resourceune entité exposée par l'API : user, article, commande...
⚠️ Pièges fréquents
  • Mélanger verbes dans l'URL (/createUser, /deleteArticle) est anti-REST — ça casse la prédictibilité et complique la documentation.
  • REST n'est pas un protocole mais un style — il y a plusieurs façons de l'interpréter. Les conventions les plus suivies sont celles décrites ici.
💡 Astuce

Rappel : voir la fiche 231A sur la requête HTTP, la fiche 231B sur les méthodes, et la fiche 236 sur le format JSON échangé.

JS · Fiche Originale

Fiche 236 — JSON
💡 En clair

Les API échangent le plus souvent du JSON (JavaScript Object Notation) — un format texte léger, lisible par un humain ET par une machine, indépendant du langage. C'est le standard de fait pour les échanges web : à peu près toutes les API modernes renvoient du JSON.

Exemple de réponse JSON d'une API :

JS
{
  "ville": "Dakar",
  "temperature": 28,
  "condition": "Ensoleillé",
  "humidite": 65,
  "previsions": [
    { "jour": "Lundi", "temp": 27 },
    { "jour": "Mardi", "temp": 29 }
  ]
}
✏️ Ligne par ligne
"ville": "Dakar"clé et valeur string — les guillemets sont OBLIGATOIRES.
"temperature": 28valeur numérique — pas de guillemets.
"condition": "Ensoleillé"autre string.
"previsions": [...]un tableau JSON d'objets JSON — imbriqués.

Règles strictes du JSON :

JS
// ✅ Correct
{ "nom": "Awa", "age": 25 }

// ❌ Faux — clé sans guillemets
{ nom: "Awa" }

// ❌ Faux — guillemets simples
{ 'nom': 'Awa' }

// ❌ Faux — virgule en trop
{ "nom": "Awa", }

// ❌ Faux — commentaires interdits
{ "nom": "Awa" } // test
📖 Mots à connaître
JSONJavaScript Object Notation — format texte universel pour échanger des données.
cléchaîne entre guillemets doubles obligatoirement.
valeurstring, nombre, booléen, null, objet ou tableau.
sérialisationconvertir un objet JS en chaîne JSON via JSON.stringify() — voir fiche 174.
⚠️ Pièges fréquents
  • Le JSON est strict : pas de guillemets simples, pas de commentaires, pas de virgule finale. Une erreur de syntaxe fait échouer JSON.parse().
  • En JSON, les clés DOIVENT être entre guillemets doubles — contrairement aux objets JS où on peut omettre les guillemets si la clé est un identifiant valide.
💡 Astuce

Rappel : voir la fiche 172 sur JSON, la fiche 174 sur JSON.stringify(), la fiche 175 sur JSON.parse(), et la fiche 238 sur response.json().

JS · Fiche Originale

Fiche 237a — fetch() : lancer une requete
💡 En clair

fetch() est la fonction moderne de JavaScript pour envoyer des requetes HTTP. Elle remplace XMLHttpRequest et retourne une Promise.

✏ Syntaxe generale

fetch(url) — forme minimale (GET par defaut).

fetch(url, options) — avec method, headers, body...

JS
fetch(url)
fetch(url, options)

Exemple minimal :

JS
fetch("https://api.exemple.com/users")
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(erreur => console.log(erreur));

fetch() retourne une Promise qui se resout quand le serveur repond.

⚠ fetch() ne renvoie PAS directement les donnees

Il renvoie un objet Response. Pour obtenir les donnees, il faut appeler response.json() (voir fiche 238).

🌐 Exemple concret

Une appli qui affiche la liste des utilisateurs :

JS
fetch("https://jsonplaceholder.typicode.com/users")
  .then(response => response.json())
  .then(users => {
    users.forEach(user => {
      console.log(user.name);
    });
  });

JS · Fiche Originale

Fiche 237b — fetch() : recevoir une reponse
💡 En clair

Quand fetch() reussit, il renvoie un objet Response qui contient toutes les infos de la reponse du serveur.

📖 Proprietes principales de Response
response.statusCode HTTP (200, 404, 500...)
response.oktrue si status entre 200 et 299
response.statusTextMessage du code (ex: "OK")
response.headersHeaders de la reponse
response.urlURL finale appelee

Exemple :

JS
fetch("https://api.exemple.com/users/1")
  .then(response => {
    console.log(response.status);      // 200
    console.log(response.ok);          // true
    console.log(response.statusText);  // "OK"
    console.log(response.url);         // URL finale
  });
⚠ fetch() ne rejette PAS sur les erreurs HTTP

Contrairement a ce qu on pourrait croire, fetch() ne lance pas d erreur si le serveur renvoie 404 ou 500. Il faut verifier manuellement response.ok :

JS
fetch(url)
  .then(response => {
    if (!response.ok) {
      throw new Error(`Erreur HTTP ${response.status}`);
    }
    return response.json();
  })
  .then(data => console.log(data))
  .catch(erreur => console.log(erreur));

.catch() ne se declenche que si la requete echoue reseau (pas de connexion, URL invalide). Pour une erreur serveur, c est .ok qui le dit.

JS · Fiche Originale

Fiche 238 — response.json()
💡 En clair

response.json() transforme le corps de la réponse (du texte JSON) en objet JavaScript. C'est la méthode la plus utilisée après un fetch(). Elle renvoie une Promise — il faut l'attendre avec .then() ou await.

Exemple avec .then() :

JS
fetch("https://api.exemple.com/users")
  .then(response => response.json())  // 1er .then : parse le JSON
  .then(data => console.log(data));  // 2e .then : exploite les données

// 1er .then reçoit la Response, renvoie la Promise de parsing
// 2e .then reçoit les données JavaScript (objet ou tableau)
Console
{ id: 1, nom: 'Awa' }, { id: 2, nom: 'John' }

Exemple avec async/await (plus lisible) :

JS
async function charger() {
  const response = await fetch("https://api.exemple.com/users");
  const data = await response.json();   // await car .json() est asynchrone
  console.log(data);
  console.log("Nombre d'users :", data.length);
}

charger();
Console
{ id: 1, nom: 'Awa' }, { id: 2, nom: 'John' }
Nombre d'users : 2
✏️ Ligne par ligne
response.json()parse le body JSON en objet JS — renvoie une Promise.
await response.json()attend que le parsing soit terminé avant de continuer.
data.lengthdata est maintenant un vrai tableau JS — on peut utiliser .length, .map, etc.

Autres méthodes de lecture selon le type de réponse :

JS
response.json()      // Objet / tableau (JSON)
response.text()       // Texte brut (HTML, CSV, etc.)
response.blob()       // Fichier binaire (image, vidéo, PDF)
response.formData()   // Formulaire multipart (upload de fichiers)
response.arrayBuffer() // Données binaires brutes

Exemple avec response.text() :

JS
fetch("https://api.exemple.com/hello.txt")
  .then(r => r.text())
  .then(texte => console.log(texte));  // "Bonjour"
Console
Bonjour
📖 Mots à connaître
response.json()parse le body JSON en objet JS — renvoie une Promise.
Promiseobjet représentant une valeur future — voir chapitre 18.
async/awaitsyntaxe moderne pour écrire de l'asynchrone comme du synchrone — voir chapitre 19.
response.text()alternative pour lire du texte brut — voir fiche 237A.
⚠️ Pièges fréquents
  • Le body ne peut être lu qu'une seule fois — appeler deux fois response.json() échoue avec une erreur.
  • Si le body n'est pas du JSON valide, response.json() lève une SyntaxError — toujours entourer d'un try/catch (ou .catch()).
💡 Astuce

Rappel : voir la fiche 175 sur JSON.parse() (mécanisme sous-jacent), la fiche 172 sur JSON, et le chapitre 19 sur async/await.

JS · Fiche Originale

Fiche 239 — async/await avec Fetch
💡 En clair

async/await rend le code Fetch beaucoup plus lisible qu avec les .then() imbriques. On ecrit le code asynchrone comme s il etait synchrone.

✏ Syntaxe generale

Toute fonction qui utilise await doit etre declaree async. On entoure le tout d un try...catch pour gerer les erreurs.

JS
async function charger() {
  try {
    let response = await fetch(url);
    let data = await response.json();
    console.log(data);
  } catch (erreur) {
    console.log("Erreur :", erreur.message);
  }
}

Comparaison : .then() vs async/await

JS
// Avec .then()
fetch(url)
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(erreur => console.log(erreur));

// Avec async/await (plus lisible)
async function charger() {
  let response = await fetch(url);
  let data = await response.json();
  console.log(data);
}
💡 Pourquoi async/await

Le code se lit de haut en bas, comme du code synchrone. Plus lisible, plus facile a debugger, plus facile a modifier. C est la syntaxe recommandee aujourd hui.

JS · Fiche Originale

Fiche 240a — POST avec Fetch
💡 En clair

POST sert a envoyer des donnees au serveur, generalement pour creer une nouvelle ressource.

✏ Syntaxe generale

Contrairement a GET, il faut preciser method: "POST", les headers (type de contenu) et le body (donnees a envoyer).

JS
fetch(url, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify(donnees)
})

Exemple simple :

JS
fetch("https://api.exemple.com/users", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ nom: "Awa", age: 25 })
})
  .then(response => response.json())
  .then(data => console.log("Cree :", data))
  .catch(erreur => console.log(erreur));

Avec async/await :

JS
async function creerUtilisateur(user) {
  let response = await fetch("https://api.exemple.com/users", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(user)
  });

  let data = await response.json();
  console.log("Utilisateur cree :", data);
}

creerUtilisateur({ nom: "Awa", age: 25 });
📖 Difference GET vs POST
RoleGET : recuperer · POST : envoyer / creer
DonneesGET : dans l URL · POST : dans le body
VisibleGET : ✅ oui (URL) · POST : ❌ non (body)
SecuriteGET : moins sur · POST : plus sur
🌐 Exemple concret

Un formulaire d inscription envoie les donnees au serveur :

JS
form.addEventListener("submit", async (event) => {
  event.preventDefault();

  let user = {
    pseudo: document.getElementById("pseudo").value,
    email: document.getElementById("mail").value
  };

  let response = await fetch("https://api.exemple.com/inscription", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(user)
  });

  if (response.ok) {
    console.log("Inscription reussie");
  }
});

JS · Fiche Originale

Fiche 240b — JSON.stringify() et headers
💡 En clair

Quand on envoie des donnees avec POST, PUT ou PATCH, on envoie souvent du JSON. Le body d une requete HTTP ne peut transporter que du texte : il faut donc transformer l objet JavaScript en texte avec JSON.stringify().

✏ Le duo indispensable

JS
headers: { "Content-Type": "application/json" },
body: JSON.stringify(donnees)

Content-Type: application/json → previent le serveur que le body est du JSON. JSON.stringify(donnees) → convertit l objet JS en texte JSON.

Exemple complet :

JS
let article = {
  titre: "Mon article",
  contenu: "Voici le contenu...",
  auteur: "Awa"
};

fetch("https://api.exemple.com/articles", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify(article)
})
  .then(response => response.json())
  .then(data => console.log("Article cree :", data));
⚠ Erreur classique

Sans JSON.stringify(), le body devient [object Object] — le serveur ne comprend rien.

JS
// &#10060; FAUX
body: article
// Le serveur recoit "[object Object]"

// &#9989; CORRECT
body: JSON.stringify(article)
// Le serveur recoit '{"titre":"Mon article",...}'
💡 Headers — informations supplementaires

Les headers transportent des infos annexes : type de contenu, authentification, langue...

📖 Headers les plus courants
Content-TypeType du body (application/json, text/html...)
AcceptType de reponse attendu
AuthorizationJeton d authentification (Bearer <token>)
User-AgentInfo sur le client (navigateur)
Cache-ControlGestion du cache

Exemple : authentification :

JS
fetch("https://api.exemple.com/profil", {
  headers: {
    "Authorization": "Bearer abc123xyz"
  }
});

Sans ce header, le serveur repond 401 Unauthorized.

JS · Fiche Originale

Fiche 241 — Erreurs Fetch
💡 En clair

fetch() a une particularite piegeuse : il ne rejette pas la Promise en cas d erreur HTTP (404, 500...). Il faut verifier manuellement response.ok.

📖 Les deux types d erreurs
Erreur reseauPas de connexion, URL invalide — fetch() rejette ✅
Erreur HTTP404, 500, 401... — fetch() ne rejette PAS ❌
✏ Verifier manuellement le statut

JS
fetch(url)
  .then(response => {
    if (!response.ok) {
      throw new Error(`Erreur HTTP ${response.status}`);
    }
    return response.json();
  })
  .then(data => console.log(data))
  .catch(erreur => console.log("Erreur :", erreur.message));

Le throw dans le .then() declenche le .catch().

Avec async/await + try/catch :

JS
async function charger(url) {
  try {
    let response = await fetch(url);

    if (!response.ok) {
      throw new Error(`Erreur HTTP ${response.status}`);
    }

    let data = await response.json();
    return data;
  } catch (erreur) {
    console.log("Echec :", erreur.message);
  }
}
💡 Gerer plusieurs codes

On peut adapter le message selon le code HTTP recu :

JS
async function charger(url) {
  let response = await fetch(url);

  if (response.status === 404) {
    console.log("Ressource introuvable");
  } else if (response.status === 401) {
    console.log("Non autorise");
  } else if (response.status >= 500) {
    console.log("Erreur serveur");
  } else if (response.ok) {
    return response.json();
  }
}
🔄 Timeout avec AbortController

fetch() n a pas de timeout par defaut. On peut en ajouter avec AbortController :

JS
let controller = new AbortController();
setTimeout(() => controller.abort(), 5000); // 5 secondes max

fetch(url, { signal: controller.signal })
  .then(response => response.json())
  .catch(erreur => console.log("Timeout ou erreur :", erreur));

JS · Fiche Originale

Fiche 242a — Recuperer des donnees depuis une API
💡 En clair

Recuperer des donnees depuis une API suit toujours le meme cycle : fetch() → response.json() → utiliser les donnees.

✏ Cycle complet avec async/await

JS
async function chargerUtilisateurs() {
  try {
    // 1. Envoyer la requete
    let response = await fetch("https://api.exemple.com/users");

    // 2. Verifier le statut
    if (!response.ok) {
      throw new Error(`Erreur HTTP ${response.status}`);
    }

    // 3. Convertir en JSON
    let users = await response.json();

    // 4. Utiliser les donnees
    console.log(users);
  } catch (erreur) {
    console.log("Echec du chargement :", erreur.message);
  }
}
💡 GET avec parametres dans l URL

Pour filtrer, on ajoute des parametres a l URL :

JS
fetch("https://api.exemple.com/articles?categorie=tech&limit=10")

Tout ce qui suit ? s appelle la query string. Les parametres sont separe par &.

Construire l URL proprement avec URLSearchParams :

JS
let params = new URLSearchParams({
  categorie: "tech",
  limit: 10
});

fetch(`https://api.exemple.com/articles?${params}`)
  .then(response => response.json())
  .then(data => console.log(data));

Resultat : ?categorie=tech&limit=10

JS · Fiche Originale

Fiche 242b — Afficher les donnees dans le DOM
💡 En clair

Une fois les donnees recues de l API, il faut les afficher dans la page en creant des elements DOM pour chaque item.

✏ Pattern type

JS
async function afficherArticles() {
  let response = await fetch("https://api.exemple.com/articles");
  let articles = await response.json();

  // Pour chaque article, creer un element HTML
  articles.forEach(article => {
    let h2 = document.createElement("h2");
    h2.textContent = article.titre;
    document.body.appendChild(h2);
  });
}

Pattern detaille :

JS
async function afficherArticles() {
  try {
    let response = await fetch("https://api.exemple.com/articles");

    if (!response.ok) throw new Error("Erreur HTTP");

    let articles = await response.json();
    let conteneur = document.getElementById("articles");

    conteneur.innerHTML = ""; // vider avant de remplir

    articles.forEach(article => {
      let div = document.createElement("div");
      div.classList.add("article");

      let h2 = document.createElement("h2");
      h2.textContent = article.titre;

      let p = document.createElement("p");
      p.textContent = article.extrait;

      div.appendChild(h2);
      div.appendChild(p);
      conteneur.appendChild(div);
    });
  } catch (erreur) {
    console.log("Erreur :", erreur.message);
  }
}
⚠ Faille XSS

Ne JAMAIS utiliser innerHTML avec du contenu provenant d une API si elle n est pas 100% fiable. Toujours preferer textContent pour le texte utilisateur.

JS · Fiche Originale

Fiche 243 — Cycle Fetch complet
💡 En clair

Le cycle complet d une requete Fetch, de l envoi jusqu au rendu, suit ces etapes :

Cycle complet
1. fetch(url)              --> envoie la requete HTTP
2. response = await fetch   --> recoit l objet Response
3. response.ok ?             --> verifie le statut
4. data = response.json()    --> convertit le body en JS
5. data.forEach(...)         --> utilise les donnees
6. catch(erreur)             --> gere les erreurs

Exemple complet : liste d utilisateurs + rendu dans le DOM

JS
async function chargerEtAfficher() {
  try {
    // 1-3. Requete + verification
    let response = await fetch("https://api.exemple.com/users");
    if (!response.ok) throw new Error(`Erreur ${response.status}`);

    // 4. Conversion JSON
    let users = await response.json();

    // 5. Rendu dans le DOM
    let liste = document.getElementById("liste");
    liste.innerHTML = "";

    users.forEach(user => {
      let li = document.createElement("li");
      li.textContent = `${user.nom} (${user.email})`;
      liste.appendChild(li);
    });
  } catch (erreur) {
    // 6. Gestion d erreur
    console.log("Echec :", erreur.message);
  }
}

chargerEtAfficher();

JS · Fiche Originale

Fiche 244 — Carte mentale HTTP / API / Fetch
💡 En clair

HTTP, API et Fetch sont 3 notions qui travaillent ensemble : HTTP est le protocole, API est le service expose, Fetch est l outil JavaScript pour les utiliser.

Carte mentale
HTTP (protocole)
 +-- Methodes : GET, POST, PUT, PATCH, DELETE
 +-- Codes : 200, 201, 400, 401, 404, 500...
 +-- Headers : Content-Type, Authorization...
 |
 +--> API (service)
      +-- URL : /users, /articles, /posts...
      +-- REST : CRUD sur ressources
      +-- Reponse : souvent du JSON
      |
      +--> fetch() (outil JS)
           +-- fetch(url) -> Promise
           +-- response.json() -> objet JS
           +-- try/catch pour les erreurs
📖 Recapitulatif
HTTPLe langage navigateur ↔ serveur
APIUn service qui expose des URL pour echanger des donnees
RESTStyle d API utilisant les methodes HTTP sur des ressources
JSONFormat texte des reponses (leger, universel)
fetch()Fonction JS moderne pour envoyer des requetes
response.json()Convertit la reponse en objet JS
async/awaitSyntaxe moderne pour ecrire le fetch de facon lisible
try/catchIndispensable car fetch ne rejette pas sur 404/500
🌐 Exemple concret

Quand tu ouvres Twitter :

1. HTTP transporte la requete (GET /feed).

2. L API Twitter renvoie une liste de tweets en JSON.

3. fetch() recupere la reponse.

4. response.json() convertit le JSON en objet JavaScript.

5. JavaScript affiche les tweets dans le DOM.

24
Chapitre 243 fiches

Introduction a Node.js

Executer JavaScript cote serveur

JS - Fiche originale

Fiche 245 - Qu'est-ce que Node.js ?
💡 En clair

Node.js est un environnement d'exécution JavaScript hors du navigateur. Il utilise le moteur V8 de Chrome pour faire tourner du JS sur ta machine ou un serveur — pas seulement dans une page web.

📖 Mots à connaître
V8le moteur JavaScript de Google Chrome, repris par Node.js pour exécuter le code
runtimeenvironnement d'exécution — tout ce qui permet à un langage de tourner (moteur + APIs)
serveurun programme qui écoute des requêtes et répond — Node.js peut en créer
JS
// bonjour.js
console.log("Bonjour depuis Node.js !");
console.log("Version :", process.version);
Terminal
$ node bonjour.js
Bonjour depuis Node.js !
Version : v20.10.0
✏️ Ligne par ligne
console.log("Bonjour ...")même instruction qu'en navigateur, mais exécutée par Node.js
process.versionobjet spécifique à Node — n'existe pas dans le navigateur
$ node bonjour.jscommande terminal qui lance le fichier avec Node
⚠️ Pièges fréquents
  • Node.js n'a pas de DOM : pas de document, pas de window. Ces objets n'existent que dans le navigateur.
  • Node.js a accès au système de fichiers, au réseau, au processus — des choses interdites au navigateur pour des raisons de sécurité.
💡 Astuce

Un seul langage (JavaScript) pour le frontend (navigateur) ET le backend (Node.js). C'est l'argument principal de Node.js.

JS - Fiche originale

Fiche 246 - JavaScript navigateur vs Node.js
💡 En clair

Le langage JavaScript est le même des deux côtés. Ce qui change : les APIs disponibles. Le navigateur expose le DOM ; Node.js expose les fichiers, le réseau bas niveau, le processus.

📖 Mots à connaître
windowobjet global du navigateur — absent de Node.js
globalobjet global de Node.js (et globalThis partout)
documentla page HTML manipulable — uniquement dans le navigateur
processl'objet global de Node.js pour interagir avec le processus courant
JS
// Navigateur uniquement
document.getElementById("titre").textContent = "Salut";
console.log(window.location.href);

// Node.js uniquement
const fs = require("fs");
fs.writeFileSync("test.txt", "Bonjour");
console.log(process.platform); // "linux", "darwin", "win32"
✏️ Ligne par ligne
document.getElementById(...)manipule le DOM — seulement dans un navigateur
window.location.hrefobjet global du navigateur — absent de Node
fs.writeFileSync(...)écrit un fichier — seulement dans Node.js
process.platforminfo système — seulement dans Node.js
⚠️ Pièges fréquents
  • document n'existe pas dans Node.js : écrire document.title provoque ReferenceError.
  • require et process n'existent pas dans le navigateur — il faut un bundler ou des modules ES.
💡 Astuce

Commun aux deux : console.log, Math, JSON, Promise, setTimeout, Array, Object. Ce sont les APIs standard du langage.

JS - Fiche originale

Fiche 247 - Executer un fichier avec Node.js
💡 En clair

Pour exécuter un fichier JavaScript avec Node.js, on utilise la commande node fichier.js dans le terminal. Node lit le fichier, l'analyse, l'exécute, puis se termine quand il n'y a plus rien à faire.

JS
// somme.js
const a = Number(process.argv[2]);
const b = Number(process.argv[3]);
console.log("Somme :", a + b);
Terminal
$ node somme.js 5 3
Somme : 8
✏️ Ligne par ligne
$ node somme.js 5 3commande : lance Node.js sur le fichier somme.js avec 2 arguments
process.argv[2]récupère le 3e argument (les 2 premiers sont "node" et le chemin du script)
Number(...)convertit la chaîne "5" en nombre 5
console.log("Somme :", a + b)affiche le résultat
⚠️ Pièges fréquents
  • process.argv[0] est le chemin de Node, argv[1] est le chemin du script. Tes arguments commencent à l'index 2.
  • Sans Number(...), "5" + "3" donne la chaîne "53" (concaténation), pas 8.
💡 Astuce

Pour relancer automatiquement à chaque modification : installe nodemon (npm i -g nodemon) puis lance nodemon somme.js. Plus besoin de relancer à la main.

25
Chapitre 255 fiches

Packages Node.js

Installer et piloter les dependances

JS - Fiche originale

Fiche 248 - npm
💡 En clair

npm (Node Package Manager) est le gestionnaire de paquets livré avec Node.js. Il installe, met à jour et retire des bibliothèques JavaScript tierces — il y en a plus d'1 million sur le registre public.

📖 Mots à connaître
paquet / packageune bibliothèque JavaScript publiée sur le registre npm
node_modules/dossier où npm installe les paquets téléchargés
package.jsonfichier qui liste les paquets utilisés par ton projet
JS
# Installer un paquet
npm install express

# Installer en dépendance de dev
npm install --save-dev nodemon

# Installer globalement
npm install -g nodemon

# Désinstaller
npm uninstall express

# Lister ce qui est installé
npm list
Terminal
$ npm install express
added 57 packages in 2s
✏️ Ligne par ligne
npm install expresstélécharge express + ses dépendances dans node_modules/
--save-devmarque le paquet comme utile seulement en développement
-ginstalle globalement — accessible depuis n'importe quel dossier
⚠️ Pièges fréquents
  • npm install sans argument (dans un projet existant) réinstalle tous les paquets listés dans package.json.
  • N'installe jamais en -g un paquet qui doit être versionné avec ton projet — il ne sera pas disponible pour les autres développeurs.
💡 Astuce

Toujours npm init -y avant d'installer quoi que ce soit : ça crée le package.json qui stockera tes dépendances.

JS - Fiche originale

Fiche 249 - package.json
💡 En clair

package.json est la carte d'identité d'un projet Node.js. Il contient : nom, version, scripts, dépendances de production et de développement. Sans lui, npm ne sait pas quoi installer.

📖 Mots à connaître
namenom du projet (minuscules, sans espaces)
versionversion sémantique : MAJEUR.MINEUR.PATCH (ex : 1.4.2)
dependenciespaquets nécessaires en production
devDependenciespaquets utiles seulement pendant le développement
scriptsraccourcis de commandes lancés avec npm run <nom>
JS
{
  "name": "mon-projet",
  "version": "1.0.0",
  "description": "Une API Express",
  "main": "app.js",
  "scripts": {
    "start": "node app.js",
    "dev": "nodemon app.js"
  },
  "dependencies": {
    "express": "^4.18.0"
  },
  "devDependencies": {
    "nodemon": "^3.0.0"
  }
}
✏️ Ligne par ligne
"name": "mon-projet"identifiant du projet — doit être unique si publié sur npm
"scripts": { ... }définit les raccourcis : npm run dev lance nodemon
"dependencies"paquets installés en production : express, mongoose, etc.
"devDependencies"paquets utiles au dev : tests, lint, rechargement auto
⚠️ Pièges fréquents
  • N'édite jamais package.json à la main pour ajouter une dépendance — utilise npm install <paquet> pour éviter les erreurs de version.
  • Le ^ devant une version autorise les mises à jour mineures : ^4.18.0 accepte 4.19.0 mais pas 5.0.0.
💡 Astuce

Pour créer un package.json rapidement : npm init -y génère un fichier par défaut sans poser de questions.

JS - Fiche originale

Fiche 250 - node_modules
💡 En clair

node_modules/ est le dossier où npm installe tous les paquets (et leurs sous-dépendances). C'est souvent le dossier le plus gros d'un projet — parfois des centaines de Mo.

JS
# .gitignore — TOUJOURS ignorer node_modules
node_modules/
.env

# Quand on clone un projet :
git clone https://github.com/user/projet.git
cd projet
npm install   # recrée node_modules/ à partir de package.json
Terminal
$ npm install
added 247 packages in 5s
✏️ Ligne par ligne
node_modules/ dans .gitignorejamais versionné — trop gros et reproductible
npm installlit package.json et recrée tout le dossier node_modules/
npm ciinstallation stricte basée sur package-lock.json (CI/CD)
⚠️ Pièges fréquents
  • Ne JAMAIS committer node_modules/ dans Git. Ajoute-le au .gitignore dès la création du projet.
  • Si tu supprimes node_modules/, pas de panique : un simple npm install le reconstitue à l'identique.
💡 Astuce

Avant d'envoyer ton code en production ou de le partager, supprime node_modules/ : il sera recréé par npm install ou npm ci.

JS - Fiche originale

Fiche 251 - Gerer les dependances
💡 En clair

Une dépendance est un paquet externe dont ton projet a besoin pour fonctionner. Il y en a deux types : dependencies (production) et devDependencies (développement uniquement).

📖 Mots à connaître
dependenciespaquets indispensables au fonctionnement de l'app en production
devDependenciespaquets utiles seulement pendant le développement (tests, lint, rechargement auto)
dépendance transitivepaquet dont ton paquet dépend indirectement (sous-dépendance)
JS
# Ajouter en dépendance de production
npm install express

# Ajouter en dépendance de dev
npm install --save-dev jest

# Mettre à jour les paquets
npm update

# Retirer un paquet
npm uninstall express
Terminal
$ npm install --save-dev jest
added 56 packages in 1s
✏️ Ligne par ligne
npm install expressajoute à dependencies — installé en prod
--save-dev jestajoute à devDependencies — ignoré en prod
npm updatemet à jour les paquets dans les limites autorisées par ^ et ~
npm uninstall expressretire le paquet et l'enlève de package.json
⚠️ Pièges fréquents
  • Mets en devDependencies tout ce qui n'est utile qu'au développement : tests, lint, bundlers, rechargement auto. Sinon tu alourdis la prod inutilement.
  • En production, npm install --omit=dev installe uniquement les dependencies.
💡 Astuce

package-lock.json fige les versions exactes des dépendances (y compris transitives). Toujours le committer pour des builds reproductibles.

JS - Fiche originale

Fiche 252 - Les scripts npm
💡 En clair

Les scripts npm sont des raccourcis de commandes définis dans package.json sous la clé scripts. On les lance avec npm run <nom> (ou directement npm start, npm test).

JS
{
  "scripts": {
    "start": "node server.js",
    "dev": "nodemon server.js",
    "test": "jest",
    "lint": "eslint src/",
    "build": "webpack --mode production",
    "check": "npm run lint && npm run test"
  }
}
Terminal
$ npm run dev
> mon-projet@1.0.0 dev
> nodemon server.js
Serveur sur http://localhost:3000
✏️ Ligne par ligne
"start": "node server.js"script spécial — lancé avec npm start (sans "run")
"dev": "nodemon server.js"recharge le serveur à chaque modification
"test": "jest"script spécial — lancé avec npm test
"check": "npm run lint && npm run test"enchaîne deux scripts avec &&
⚠️ Pièges fréquents
  • npm start et npm test sont des scripts spéciaux : ils se lancent sans run. Les autres nécessitent npm run <nom>.
  • && enchaîne les commandes : la 2e ne s'exécute que si la 1re réussit. Pour exécuter dans tous les cas, utilise & (à éviter dans les scripts).
💡 Astuce

Standardise tes scripts : dev pour développer, start pour la prod, test pour les tests, lint pour la qualité du code. Les développeurs s'y retrouvent tout de suite.

26
Chapitre 2610 fiches

Configuration et modules Node.js

Configurer, decouper et reutiliser une application

JS - Fiche originale

Fiche 253 - Variables d'environnement
💡 En clair

Une variable d'environnement est une valeur stockée en dehors du code, dans le système ou un fichier .env. On y met tout ce qui est secret ou variable selon l'environnement (clés API, mots de passe, ports).

📖 Mots à connaître
.envfichier texte à la racine du projet contenant des paires CLE=valeur
dotenvpaquet qui charge le fichier .env dans process.env au démarrage
process.envobjet global Node.js contenant toutes les variables d'environnement
JS
# .env (à la racine du projet)
PORT=3000
DB_PASSWORD=monMotDePasseSecret
API_KEY=abc123xyz
NODE_ENV=development

Chargement dans le code avec dotenv :

JS
// app.js (tout en haut)
require("dotenv").config();

const port = process.env.PORT;
const apiKey = process.env.API_KEY;
console.log(`Serveur sur le port ${port}`);
console.log(`Clé : ${apiKey ? "OK" : "manquante"}`);
Console
Serveur sur le port 3000
Clé : OK
✏️ Ligne par ligne
require("dotenv").config()lit le fichier .env et peuple process.env
process.env.PORTrécupère la valeur définie dans .env
process.env.NODE_ENVconvention : "development" ou "production"
⚠️ Pièges fréquents
  • Ne JAMAIS committer le fichier .env — il contient tes secrets. Ajoute-le au .gitignore.
  • À la place, versionne un .env.example avec la même structure mais des valeurs vides.
💡 Astuce

Vérifie les variables obligatoires au démarrage : si JWT_SECRET manque, fais process.exit(1) — mieux vaut un crash qu'une app qui tourne sans sécurité.

JS - Fiche originale

Fiche 254 - L'objet process
💡 En clair

process est un objet global de Node.js qui décrit et contrôle le processus en cours. Il expose l'environnement (process.env), les arguments reçus (process.argv), et permet de quitter le programme (process.exit()).

📖 Mots à connaître
process.envvariables d'environnement (issues du système ou de .env)
process.argvtableau des arguments passés à la commande node
process.cwd()retourne le dossier courant d'exécution
process.exit(code)termine le programme (0 = succès, 1 = erreur)
process.platformsystème d'exploitation : "linux", "darwin", "win32"
JS
// Lister les arguments de la ligne de commande
const args = process.argv.slice(2);
console.log("Args :", args);
console.log("Plateforme :", process.platform);
console.log("Dossier :", process.cwd());

// Quitter proprement
if (!process.env.API_KEY) {
  console.error("API_KEY manquante");
  process.exit(1);
}
Terminal
$ node app.js Awa 25
Args : [ 'Awa', '25' ]
Plateforme : linux
Dossier : /home/awa/mon-projet
✏️ Ligne par ligne
process.argv.slice(2)récupère les arguments utilisateur (les 2 premiers sont "node" et le script)
process.platformutile pour adapter le code selon l'OS
process.cwd()cwd = "current working directory"
process.exit(1)quitte avec un code d'erreur — convention Unix
⚠️ Pièges fréquents
  • process.argv[0] est le chemin de Node, argv[1] est le chemin du script. Tes arguments commencent à l'index 2.
  • process.exit(0) = succès, process.exit(1) = erreur. Convention Unix reprise par tous les outils de CI/CD.
💡 Astuce

Pour écouter l'arrêt du programme (Ctrl+C) : process.on("SIGINT", () => { ... }) — utile pour fermer une connexion à la base proprement.

JS - Fiche originale

Fiche 255 - Le systeme de fichiers
💡 En clair

Le module fs (File System) permet à Node.js de lire, écrire, supprimer des fichiers et manipuler les dossiers. C'est une API essentielle, absente du navigateur pour des raisons de sécurité.

📖 Mots à connaître
fsmodule natif de Node.js pour les opérations sur les fichiers
synchronebloque le programme jusqu'à la fin de l'opération — à éviter
asynchronerend la main immédiatement, prévient quand c'est fini
fs.promisesversion moderne basée sur les Promesses (compatible async/await)
JS
// CommonJS
const fs = require("fs");
const fsPromises = require("fs").promises;

// ES Modules
import fs from "fs";
import fsPromises from "fs/promises";

Trois versions de chaque méthode :

JS
// 1) Synchrone — bloque le programme
const data = fs.readFileSync("test.txt", "utf-8");

// 2) Asynchrone avec callback
fs.readFile("test.txt", "utf-8", (err, data) => {
  if (err) return console.log(err);
  console.log(data);
});

// 3) Asynchrone moderne (Promise + async/await)
const data = await fsPromises.readFile("test.txt", "utf-8");
✏️ Ligne par ligne
fs.readFileSync(...)bloque — à éviter sauf au démarrage
fs.readFile(..., callback)asynchrone ancien style avec callback (err, data)
fsPromises.readFile(...)moderne — renvoie une Promise, parfait avec await
⚠️ Pièges fréquents
  • Les versions synchrones (*Sync) bloquent l'Event Loop : à éviter absolument dans un serveur. Acceptables seulement au démarrage d'un script CLI court.
  • En cas d'erreur, toujours vérifier err avant d'utiliser data — sinon crash.
💡 Astuce

Préfère systématiquement fs/promises avec async/await : code plus lisible, gestion d'erreur centralisée dans try/catch.

JS - Fiche originale

Fiche 256 - Lire un fichier
💡 En clair

fs.readFile() lit un fichier de façon asynchrone. Sans encodage, on récupère un Buffer binaire ; avec "utf-8", on récupère directement une chaîne de caractères.

📖 Mots à connaître
cheminadresse du fichier à lire (absolue ou relative)
encodage"utf-8" pour du texte — sinon Node renvoie un Buffer binaire
Bufferobjet Node.js qui représente des données binaires brutes
JS
// Version moderne avec async/await
const fs = require("fs").promises;

async function lire() {
  try {
    const contenu = await fs.readFile("test.txt", "utf-8");
    console.log(contenu);
  } catch (err) {
    console.log("Erreur :", err.message);
  }
}

lire();
Console
Bonjour depuis le fichier !
✏️ Ligne par ligne
require("fs").promisesrécupère la version Promise de fs
await fs.readFile("test.txt", "utf-8")attend la fin de la lecture puis renvoie le texte
try { ... } catch (err)capture les erreurs (fichier introuvable, permissions...)
⚠️ Pièges fréquents
  • Sans l'argument "utf-8", fs.readFile renvoie un Buffer (données binaires). Pour afficher du texte, précise toujours l'encodage.
  • Si le fichier n'existe pas : erreur ENOENT — toujours gérée par le catch.
💡 Astuce

Pour lire du JSON : JSON.parse(await fs.readFile("config.json", "utf-8")). Ou utilise require("./config.json") qui parse automatiquement (CommonJS).

JS - Fiche originale

Fiche 257 - Ecrire un fichier
💡 En clair

fs.writeFile() crée ou écrase un fichier avec du contenu. Pour ajouter à la fin sans écraser, on utilise fs.appendFile().

📖 Mots à connaître
fs.writeFileécrit du contenu — écrase si le fichier existe
fs.appendFileajoute du contenu à la fin — sans écraser
JSON.stringify(obj, null, 2)convertit un objet en JSON indenté (2 espaces)
JS
const fs = require("fs").promises;

async function ecrire() {
  // Écrire du texte
  await fs.writeFile("test.txt", "Bonjour !");
  console.log("Fichier écrit");

  // Ajouter à la fin
  await fs.appendFile("journal.log", `[${new Date().toISOString()}] OK\n`);

  // Écrire du JSON
  const user = { nom: "Awa", age: 25 };
  await fs.writeFile("user.json", JSON.stringify(user, null, 2));
}

ecrire();
Console
Fichier écrit
✏️ Ligne par ligne
fs.writeFile("test.txt", "Bonjour !")crée ou écrase test.txt avec "Bonjour !"
fs.appendFile("journal.log", ...)ajoute à la fin sans écraser le contenu existant
JSON.stringify(user, null, 2)sérialise user en JSON indenté (2 espaces par niveau)
⚠️ Pièges fréquents
  • fs.writeFile écrase le fichier s'il existe déjà. Si tu veux conserver le contenu, utilise fs.appendFile.
  • Pour écrire un objet, ne le passe pas tel quel : JSON.stringify d'abord — sinon Node écrit [object Object].
💡 Astuce

Pour un système de log simple : await fs.appendFile("app.log", ligne + "\n"). En production, on préfère des bibliothèques dédiées (Winston, Pino).

JS - Fiche originale

Fiche 258 - Les chemins avec path
💡 En clair

Le module path manipule les chemins de fichiers de façon portable : il gère automatiquement les différences entre Windows (\) et Linux/Mac (/).

📖 Mots à connaître
path.join(...)assemble des morceaux de chemin avec le bon séparateur
path.resolve(...)retourne un chemin absolu depuis le dossier courant
path.basename(chemin)retourne le nom du fichier
path.dirname(chemin)retourne le dossier parent
path.extname(chemin)retourne l'extension (.js, .json...)
__dirnamevariable globale Node (CommonJS) : dossier du fichier actuel
JS
const path = require("path");

// Assembler un chemin portable
const chemin = path.join("dossier", "data", "config.json");
console.log(chemin); // "dossier/data/config.json" (Linux)

// Chemin absolu depuis le dossier courant
const absolu = path.resolve("app.js");
console.log(absolu);

// Extraire des parties
console.log(path.basename("/home/u/app.js"));  // "app.js"
console.log(path.dirname("/home/u/app.js"));   // "/home/u"
console.log(path.extname("/home/u/app.js"));  // ".js"

// Construire un chemin fiable
const config = path.join(__dirname, "config", "app.json");
Terminal
dossier/data/config.json
/home/awa/mon-projet/app.js
app.js
/home/u
.js
✏️ Ligne par ligne
path.join("a", "b", "c")assemble des morceaux avec le séparateur de l'OS
path.resolve("app.js")retourne le chemin absolu depuis le dossier courant
path.basename / dirname / extnameextractions de parties d'un chemin
__dirnamedossier du fichier en cours d'exécution (CommonJS)
⚠️ Pièges fréquents
  • Ne construis pas de chemins avec "/" en dur : sur Windows ça casse. Utilise toujours path.join().
  • __dirname n'existe qu'en CommonJS. En ES Modules, utilise import.meta.url + fileURLToPath.
💡 Astuce

Convention : path.join(__dirname, "data", "config.json") pour référencer un fichier à côté du script, peu importe d'où on lance node.

JS - Fiche originale

Fiche 259 - Les modules Node.js
💡 En clair

Un module Node.js est un fichier JavaScript réutilisable. Il expose des valeurs avec module.exports (CommonJS) ou export (ES Modules), et en consomme avec require ou import.

📖 Mots à connaître
module natiffourni avec Node.js : fs, path, http, os, crypto...
module npminstallé via npm dans node_modules/
module localun fichier de ton projet, importé par son chemin relatif
JS
// math.js — module local
function additionner(a, b) { return a + b; }
function multiplier(a, b) { return a * b; }

module.exports = { additionner, multiplier };

// app.js — consommateur
const math = require("./math");
const fs = require("fs");          // module natif
const express = require("express"); // module npm

console.log(math.additionner(2, 3)); // 5
Console
5
✏️ Ligne par ligne
module.exports = { additionner, multiplier }rend les fonctions disponibles depuis l'extérieur (CommonJS)
require("./math")importe un module local — chemin relatif, sans extension obligatoire
require("fs")module natif — pas de ./
require("express")module npm — Node cherche dans node_modules/
⚠️ Pièges fréquents
  • En CommonJS, require("./math") cherche math.js dans le même dossier. L'extension est optionnelle mais le ./ est obligatoire pour un module local.
  • Sans ./, Node cherche d'abord dans node_modules/, puis dans les modules natifs.
💡 Astuce

Organise ton code en modules par fonctionnalité : auth.js, user.js, database.js. Chaque fichier = une responsabilité.

JS - Fiche originale

Fiche 260 - CommonJS
💡 En clair

CommonJS est le système de modules historique de Node.js. Il utilise require() pour importer et module.exports pour exporter. Toujours très répandu dans les projets existants.

📖 Mots à connaître
module.exportsobjet spécial qui contient les valeurs exportées par le module
require()fonction qui charge un module et renvoie son module.exports
objet globalmodule et require sont disponibles partout sans import
JS
// math.js
function additionner(a, b) { return a + b; }
function multiplier(a, b) { return a * b; }

module.exports = { additionner, multiplier };

// app.js
const math = require("./math");
console.log(math.additionner(2, 3)); // 5
console.log(math.multiplier(4, 5));  // 20

// Export par défaut (une seule valeur)
// utils.js
module.exports = function saluer(nom) {
  return "Bonjour " + nom;
};
// app.js
const saluer = require("./utils");
console.log(saluer("Awa")); // "Bonjour Awa"
Console
5
20
Bonjour Awa
✏️ Ligne par ligne
module.exports = { additionner, multiplier }exporte deux fonctions nommées
const math = require("./math")importe tout l'objet exports du module math
math.additionner(2, 3)appelle additionner via l'objet math
module.exports = function saluer(nom) { ... }remplace exports par une fonction unique
⚠️ Pièges fréquents
  • En CommonJS, l'extension .js est optionnelle dans require("./math"). En ES Modules, elle devient obligatoire.
  • Si tu fais module.exports = ..., tu remplaces tout l'objet exports — n'oublie pas que exports.nom ne marchera plus.
💡 Astuce

CommonJS reste le défaut dans Node.js. Pour un projet existant, garde CommonJS. Pour un nouveau projet, considère ES Modules.

JS - Fiche originale

Fiche 261 - Les modules ES
💡 En clair

ES Modules (ESM) est le système standardisé par ECMAScript. Il utilise import et export. C'est le format natif des navigateurs modernes et de plus en plus de projets Node.js.

📖 Mots à connaître
exportrend une valeur disponible depuis l'extérieur (nommé ou default)
importrécupère une valeur exportée par un autre module
"type": "module"clé à ajouter dans package.json pour activer ESM dans Node.js
.mjsextension alternative qui active ESM pour un fichier précis
JS
// math.js
export function additionner(a, b) { return a + b; }
export function multiplier(a, b) { return a * b; }

// app.js
import { additionner, multiplier } from "./math.js";
console.log(additionner(2, 3)); // 5
console.log(multiplier(4, 5));  // 20

// Default export
// utils.js
export default function saluer(nom) {
  return "Bonjour " + nom;
}
// app.js
import saluer from "./utils.js";
console.log(saluer("Awa"));
Console
5
20
Bonjour Awa
✏️ Ligne par ligne
export function additionner(...)export nommé — accessible avec import { additionner }
import { additionner } from "./math.js"extension .js obligatoire en ESM
export default function saluer(...)export par défaut — accessible sans accolades
import saluer from "./utils.js"importe le default — nom libre
⚠️ Pièges fréquents
  • En ES Modules, l'extension .js est obligatoire dans les imports : import { x } from "./math.js", sinon erreur.
  • Pour activer ESM dans Node.js : ajoute "type": "module" dans package.json, ou utilise l'extension .mjs.
💡 Astuce

ESM est le futur : la plupart des nouveaux frameworks (Vite, Next.js, Deno) l'utilisent par défaut. Pour un nouveau projet, choisis ESM.

JS - Fiche originale

Fiche 262 - require vs import
💡 En clair

require() (CommonJS) et import (ES Modules) sont deux syntaxes pour faire la même chose. CommonJS est historique et synchrone ; ESM est moderne, statique et asynchrone.

JS
// CommonJS
const fs = require("fs");
const math = require("./math");
const { additionner } = require("./math");
module.exports = { additionner, multiplier };

// ES Modules
import fs from "fs";
import * as math from "./math.js";
import { additionner } from "./math.js";
export { additionner, multiplier };
✏️ Ligne par ligne
const x = require("./math")synchrone : chargé à l'exécution, peut être dans un if
import x from "./math.js"statique : chargé à l'analyse, doit être en haut du fichier
module.exports = { ... }export CommonJS — objet dynamique
export { ... }export ESM — bindings statiques
⚠️ Pièges fréquents
  • CommonJS et ESM ne sont pas toujours interchangeables : importer un module CommonJS depuis ESM marche, mais l'inverse demande des précautions.
  • En CommonJS, require peut être conditionnel (dans un if). En ESM, import est toujours en haut du fichier — pour le chargement conditionnel, utilise await import().
💡 Astuce

Choix : nouveau projet moderne → ES Modules. Projet existant → reste en CommonJS. Bibliothèque npm → fournis les deux formats (dual package).

27
Chapitre 2719 fiches

Backend Node.js

Construire une API et ses briques essentielles

JS - Fiche originale

Fiche 263 - Creer un serveur HTTP
💡 En clair

Node.js peut créer un serveur HTTP avec le module natif http. Ce serveur écoute un port et répond aux requêtes entrantes — c'est la base de toute API ou application web.

📖 Mots à connaître
httpmodule natif de Node.js pour les échanges HTTP
portnuméro de "porte" où le serveur écoute (3000, 8080...)
reqobjet Request — contient la méthode, l'URL, les headers, le body
resobjet Response — sert à renvoyer le statut, les headers et le body
JS
const http = require("http");

const server = http.createServer((req, res) => {
  res.writeHead(200, { "Content-Type": "text/plain" });
  res.end("Bonjour !");
});

server.listen(3000, () => {
  console.log("Serveur sur http://localhost:3000");
});
Terminal
$ node server.js
Serveur sur http://localhost:3000
✏️ Ligne par ligne
http.createServer((req, res) => { ... })crée un serveur qui appelle le callback à chaque requête
res.writeHead(200, { "Content-Type": ... })écrit le statut HTTP et les headers de réponse
res.end("Bonjour !")termine la réponse et envoie le body au client
server.listen(3000, callback)démarre l'écoute sur le port 3000
⚠️ Pièges fréquents
  • Le module http est basse niveau : on doit tout gérer à la main (routing, parsing du body, gestion des erreurs). Pour un vrai projet, utilise Express (voir fiche 267).
  • Si le port est déjà utilisé : erreur EADDRINUSE. Change de port ou ferme le processus qui l'occupe.
💡 Astuce

Pour tester ton serveur : ouvre http://localhost:3000 dans un navigateur, ou utilise curl http://localhost:3000 dans le terminal.

JS - Fiche originale

Fiche 264 - Requete et reponse
💡 En clair

Chaque échange HTTP implique deux objets : req (la requête entrante — ce que le client demande) et res (la réponse sortante — ce que tu renvoies). C'est via eux que tout se passe.

📖 Mots à connaître
req.methodméthode HTTP : "GET", "POST", "PUT", "DELETE"...
req.urlchemin demandé : "/users/1?active=true"
req.headersobjet des en-têtes HTTP (Authorization, Content-Type...)
res.writeHead(status, headers)définit le statut et les headers de réponse
res.end(body)termine la réponse en envoyant le corps
JS
const server = http.createServer((req, res) => {
  console.log("Méthode :", req.method);
  console.log("URL :", req.url);
  console.log("User-Agent :", req.headers["user-agent"]);

  res.writeHead(200, { "Content-Type": "application/json" });
  res.end(JSON.stringify({
    message: "Requête reçue",
    method: req.method,
    path: req.url
  }));
});
Terminal
$ curl http://localhost:3000
Méthode : GET
URL : /
{"message":"Requête reçue","method":"GET","path":"/"}
✏️ Ligne par ligne
req.methodla méthode HTTP utilisée par le client
req.urlle chemin complet, query string incluse
req.headers["user-agent"]les headers sont des clés en minuscules
res.writeHead(200, { ... })code 200 OK + Content-Type JSON
res.end(JSON.stringify({ ... }))envoie le body — à appeler exactement une fois
⚠️ Pièges fréquents
  • res.end() doit être appelé exactement une fois par requête. Sinon : erreur Cannot set headers after they are sent.
  • En HTTP brut (module http), le body d'une requête POST n'est pas directement accessible — il faut écouter l'événement data et accumuler les chunks.
💡 Astuce

Pour renvoyer du JSON : res.writeHead(200, { "Content-Type": "application/json" }) puis res.end(JSON.stringify(obj)). Avec Express, res.json(obj) fait tout seul.

JS - Fiche originale

Fiche 266 - Middleware
💡 En clair

Un middleware est une fonction placée entre la requête et la réponse. Il peut inspecter/modifier req et res, puis appeler next() pour passer au middleware suivant. C'est le principe d'un pipeline.

📖 Mots à connaître
middlewarefonction (req, res, next) => { ... } qui intercepte chaque requête
next()fonction à appeler pour passer au middleware suivant
pipelinechaîne de middlewares exécutés dans l'ordre
JS
const express = require("express");
const app = express();

// Middleware 1 : log
app.use((req, res, next) => {
  console.log(`${req.method} ${req.url}`);
  next();
});

// Middleware 2 : parser JSON
app.use(express.json());

// Route
app.get("/", (req, res) => {
  res.send("Bonjour !");
});
Terminal
$ curl http://localhost:3000
GET /
✏️ Ligne par ligne
app.use((req, res, next) => { ... })middleware global — exécuté pour TOUTES les routes
console.log(`${req.method} ${req.url}`)log de chaque requête entrante
next()passe au middleware suivant — sinon la requête reste bloquée
app.use(express.json())middleware intégré Express : parse le body JSON
⚠️ Pièges fréquents
  • Si tu oublies next() dans un middleware personnalisé, la requête reste bloquée indéfiniment — le client attend une réponse qui ne viendra jamais.
  • L'ordre compte : les middlewares s'exécutent dans l'ordre où tu les déclares avec app.use.
💡 Astuce

Place app.use(express.json()) avant tes routes : sinon req.body sera undefined sur les requêtes POST.

JS - Fiche originale

Fiche 267 - Express : role
💡 En clair

Express est un framework minimaliste pour Node.js. Il simplifie la création de serveurs HTTP et d'API en gérant pour toi le routing, les paramètres, le parsing du body, les middlewares, et les erreurs.

📖 Mots à connaître
Expressframework web pour Node.js — le plus utilisé
routingassociation URL + méthode HTTP → handler
middlewarefonction (req, res, next) placée dans le pipeline
handlerfonction qui traite une route et renvoie une réponse
JS
// Sans Express — bas niveau
const http = require("http");
http.createServer((req, res) => {
  if (req.method === "GET" && req.url === "/users") {
    res.writeHead(200, { "Content-Type": "application/json" });
    res.end(JSON.stringify([{ id: 1 }]));
  }
}).listen(3000);

// Avec Express — lisible et concis
const express = require("express");
const app = express();

app.get("/users", (req, res) => {
  res.json([{ id: 1 }]);
});

app.listen(3000);
✏️ Ligne par ligne
http.createServer((req, res) => ...)basse niveau — il faut gérer le routing à la main
if (req.method === "GET" && req.url === "/users")test manuel de la méthode et de l'URL
app.get("/users", handler)Express abstrait le routing en une ligne
res.json([...])Express envoie automatiquement le Content-Type et stringify
⚠️ Pièges fréquents
  • Express ne fait pas tout : pas de validation automatique, pas d'ORM intégré, pas d'authentification. Tu ajoutes ces briques via middlewares et bibliothèques.
  • Express 4 n'attrape pas les erreurs des fonctions async — il faut un wrapper ou Express 5 (qui gère les Promises nativement).
💡 Astuce

Express est léger et non-opinionné : tu choisis toi-même tes bibliothèques (validation, BDD, auth). Pour un framework plus structuré : regarde NestJS, Fastify.

JS - Fiche originale

Fiche 268 - Premiere API Express
💡 En clair

Une API Express se crée en quelques lignes : on instancie l'app, on déclare des routes (app.get, app.post...), on écoute un port. C'est l'équivalent d'un serveur HTTP complet, mais lisible.

📖 Mots à connaître
appinstance Express — l'application
app.get/post/put/delete(path, handler)définit une route selon la méthode HTTP
req.paramsparamètres d'URL : /users/:id → req.params.id
req.queryquery string : ?q=js → req.query.q
req.bodycorps de la requête (POST/PUT) — exige express.json()
res.json(obj)renvoie du JSON avec le bon Content-Type
JS
const express = require("express");
const app = express();

app.use(express.json()); // parser le body JSON

// Route GET avec paramètre
app.get("/users/:id", (req, res) => {
  res.json({ id: req.params.id, nom: "Awa" });
});

// Route POST qui crée une ressource
app.post("/users", (req, res) => {
  const { nom, age } = req.body;
  res.status(201).json({ id: 1, nom, age });
});

app.listen(3000, () => console.log("API sur :3000"));
Terminal
$ curl http://localhost:3000/users/42
{"id":"42","nom":"Awa"}
$ curl -X POST -H "Content-Type: application/json" \
-d '{"nom":"Moussa","age":30}' http://localhost:3000/users
{"id":1,"nom":"Moussa","age":30}
✏️ Ligne par ligne
app.use(express.json())middleware intégré : parse req.body en JSON
app.get("/users/:id", handler)route GET avec paramètre dynamique :id
req.params.idrécupère "42" depuis /users/42
req.bodycontient le JSON envoyé en POST — nécessite express.json()
res.status(201).json({...})201 Created + corps JSON
⚠️ Pièges fréquents
  • Sans app.use(express.json()), req.body est undefined pour les requêtes POST JSON — erreur fréquente chez les débutants.
  • Les noms de paramètres :id dans l'URL correspondent à req.params.id. req.params.userId n'existerait pas pour la route /users/:id.
💡 Astuce

Convention REST : GET = lire, POST = créer, PUT/PATCH = modifier, DELETE = supprimer. Réponds 201 pour une création, 204 pour un DELETE réussi.

JS - Fiche originale

Fiche 269A - Organisation d'une API
💡 En clair

Dans une API bien organisée, la requête traverse des couches successives : routes → controllers → services → repositories → base de données. Chaque couche a un rôle unique.

📖 Mots à connaître
routesassocie une URL + méthode à un controller
controllerreçoit req/res, appelle le service, formule la réponse
servicelogique métier : règles, calculs, validation
repositoryparle à la base de données
modèle / modeldéfinit la structure des données (schéma)
JS
// Structure typique
// src/
//   routes/userRoutes.js
//   controllers/userController.js
//   services/userService.js
//   repositories/userRepository.js
//   models/User.js
//   app.js

// routes/userRoutes.js
router.get("/", userController.lister);
// controllers/userController.js
async function lister(req, res) {
  const users = await userService.getAll();
  res.json(users);
}
// services/userService.js
async function getAll() {
  return await userRepository.findAll();
}
✏️ Ligne par ligne
router.get("/", userController.lister)la route sait juste QUI appeler
const users = await userService.getAll()le controller délègue au service
return await userRepository.findAll()le service délègue au repository
res.json(users)la réponse remonte et le controller l'envoie au client
⚠️ Pièges fréquents
  • Ne mets pas de SQL directement dans un controller : on perd la séparation des responsabilités, et changer de BDD devient impossible.
  • Ne fais pas accéder le repository à req ou res — il doit être réutilisable hors d'un contexte HTTP.
💡 Astuce

Teste chaque couche indépendamment : mocke le repository pour tester le service, mocke le service pour tester le controller. C'est l'avantage majeur de la séparation.

JS - Fiche originale

Fiche 269B - Organisation d'une API
💡 En clair

Le flux d'une requête dans une API Express organisée suit un chemin précis : la requête entre par les routes, traverse middlewares, controller, service, repository, puis remonte sous forme de réponse.

JS
// Requête HTTP entrante
//     ↓
// middlewares (log, json, auth)
//     ↓
// routes/userRoutes.js
//     ↓
// controllers/userController.js
//     ↓
// services/userService.js
//     ↓
// repositories/userRepository.js
//     ↓
// Base de données
//     ↑
// (la réponse remonte par le même chemin en sens inverse)

Exemple complet — création d'un utilisateur :

JS
// POST /users avec { nom: "Awa", email: "a@b.com" }

// 1. controller/userController.js
async function creer(req, res) {
  const user = await userService.create(req.body);
  res.status(201).json(user);
}

// 2. service/userService.js
async function create(data) {
  if (!data.email.includes("@")) throw new Error("Email invalide");
  return await userRepository.create(data);
}

// 3. repository/userRepository.js
async function create(data) {
  return await db.query("INSERT INTO users ...", [data.nom, data.email]);
}
✏️ Ligne par ligne
POST /usersla requête arrive sur la route définie dans userRoutes.js
userService.create(req.body)controller délègue au service avec les données
if (!data.email.includes("@")) throw ...service valide la règle métier (email valide)
userRepository.create(data)service délègue au repository l'accès aux données
db.query("INSERT INTO users ...")repository parle SQL à la base
res.status(201).json(user)la réponse remonte jusqu'au client
⚠️ Pièges fréquents
  • Si une couche appelle une autre couche en sautant un niveau (ex : controller qui parle SQL), la séparation est cassée — refactorise.
  • Les erreurs lancées par le service doivent remonter jusqu'au middleware d'erreur — ne pas les avaler dans un try/catch silencieux.
💡 Astuce

Règle d'or : req et res ne sortent jamais du controller. Le service et le repository ne connaissent pas HTTP.

JS - Fiche originale

Fiche 270 - Controllers
💡 En clair

Un controller est la fonction qui reçoit req et renvoie res. Il ne fait presque rien lui-même : il extrait les données de la requête, appelle le service, et formule la réponse.

📖 Mots à connaître
controllerfonction (req, res) ou (req, res, next) qui gère une route
req.params / req.query / req.bodysources de données entrantes
res.json / res.statusméthodes pour formuler la réponse
JS
// controllers/userController.js
const userService = require("../services/userService");

async function lister(req, res) {
  const users = await userService.getAll();
  res.json(users);
}

async function getById(req, res) {
  const user = await userService.getById(req.params.id);
  res.json(user);
}

async function creer(req, res) {
  const user = await userService.create(req.body);
  res.status(201).json(user);
}

module.exports = { lister, getById, creer };
✏️ Ligne par ligne
async function lister(req, res) { ... }controller = fonction async qui attend le service
await userService.getAll()délègue toute la logique au service
res.json(users)renvoie le résultat au format JSON
res.status(201).json(user)201 Created — convention REST pour une création
module.exports = { lister, getById, creer }export groupé pour les routes
⚠️ Pièges fréquents
  • Un controller ne doit jamais accéder directement à la base de données ni contenir de logique métier. Sinon, le code devient impossible à tester et maintenir.
  • Ne pas oublier async : sans lui, les erreurs du service ne seront pas attrapées par Express.
💡 Astuce

Un controller devrait faire 5-10 lignes. S'il fait plus, c'est que de la logique métier y a fuité — passe-la au service.

JS - Fiche originale

Fiche 271 - Services
💡 En clair

Un service contient la logique métier de l'application : règles de validation, calculs, vérifications de stock, conditions d'âge, etc. C'est le cerveau de ton API.

📖 Mots à connaître
servicecouche avec la logique métier — ni req/res, ni SQL
logique métierrègles propres au domaine : "panier > 0", "user >= 18 ans"...
repositoryle service appelle le repository pour parler à la BDD
JS
// services/userService.js
const userRepository = require("../repositories/userRepository");

async function getAll() {
  return await userRepository.findAll();
}

async function getById(id) {
  const user = await userRepository.findById(id);
  if (!user) throw new Error("Utilisateur introuvable");
  return user;
}

async function create(data) {
  if (!data.email.includes("@")) {
    throw new Error("Email invalide");
  }
  return await userRepository.create(data);
}

module.exports = { getAll, getById, create };
✏️ Ligne par ligne
return await userRepository.findAll()le service délègue l'accès BDD au repository
if (!user) throw new Error(...)règle métier : si l'utilisateur n'existe pas → erreur
if (!data.email.includes("@")) throw ...validation métier — pas technique mais fonctionnelle
⚠️ Pièges fréquents
  • Un service ne doit jamais manipuler req ou res. Sinon, il devient dépendant d'Express et n'est plus réutilisable ailleurs.
  • Un service ne doit pas non plus écrire de SQL : c'est le rôle du repository. Sinon, on perd l'isolation de la couche données.
💡 Astuce

Si ton service fait plus que valider + appeler le repository (ex : il construit des requêtes SQL), c'est qu'une partie de la logique a fuité. Refactorise.

JS - Fiche originale

Fiche 272 - Repository
💡 En clair

Un repository est la seule couche qui parle à la base de données. Il encapsule les requêtes SQL ou les appels Mongoose, et expose des méthodes claires : findAll(), findById(id), create(data)...

📖 Mots à connaître
repositorycouche d'accès aux données — isole le SQL ou les appels ORM
findAll / findById / create / update / deleteméthodes standard d'un repository CRUD
ORMObject-Relational Mapping — Mongoose, Sequelize, Prisma...
JS
// repositories/userRepository.js (avec pg)
const db = require("../config/database");

async function findAll() {
  const rows = await db.query("SELECT * FROM users");
  return rows;
}

async function findById(id) {
  const rows = await db.query("SELECT * FROM users WHERE id = $1", [id]);
  return rows[0];
}

async function create(data) {
  const result = await db.query(
    "INSERT INTO users (nom, email) VALUES ($1, $2)",
    [data.nom, data.email]
  );
  return { id: result.insertId, ...data };
}

module.exports = { findAll, findById, create };
✏️ Ligne par ligne
db.query("SELECT * FROM users")le SQL est ici — et seulement ici
WHERE id = $1, [id]requête paramétrée — protège contre les injections SQL
return rows[0]un findById renvoie UN objet, pas un tableau
module.exports = { findAll, findById, create }le repository expose une API claire aux services
⚠️ Pièges fréquents
  • Utilise toujours des requêtes paramétrées (? ou $1) — ne jamais concaténer de valeurs utilisateur dans le SQL. Sinon : injection SQL.
  • Le repository ne doit pas contenir de règles métier (ex : "si age < 18, refuser"). Ça, c'est le rôle du service.
💡 Astuce

Avantage majeur : si tu changes de BDD (MySQL → MongoDB), tu ne réécris que les repositories. Tout le reste de l'app reste intact.

JS - Fiche originale

Fiche 273 - CRUD
💡 En clair

CRUD = Create, Read, Update, Delete — les 4 opérations de base sur toute ressource. C'est le squelette de presque toute API REST.

📖 Mots à connaître
Createcréer une ressource → HTTP POST
Readlire une ressource → HTTP GET (liste ou détail)
Updatemodifier → HTTP PUT (complet) ou PATCH (partiel)
Deletesupprimer → HTTP DELETE
JS
// routes/userRoutes.js
const express = require("express");
const router = express.Router();
const ctrl = require("../controllers/userController");

router.get("/", ctrl.lister);        // READ (liste)
router.get("/:id", ctrl.getUser);    // READ (un)
router.post("/", ctrl.creer);        // CREATE
router.put("/:id", ctrl.remplacer);  // UPDATE (complet)
router.patch("/:id", ctrl.modifier); // UPDATE (partiel)
router.delete("/:id", ctrl.supprimer);// DELETE

module.exports = router;
✏️ Ligne par ligne
router.get("/", ctrl.lister)GET /users → liste tous les utilisateurs
router.get("/:id", ctrl.getUser)GET /users/42 → un utilisateur précis
router.post("/", ctrl.creer)POST /users → crée un nouvel utilisateur
router.put("/:id", ctrl.remplacer)PUT /users/42 → remplace TOUTE la ressource
router.patch("/:id", ctrl.modifier)PATCH /users/42 → modifie uniquement les champs envoyés
router.delete("/:id", ctrl.supprimer)DELETE /users/42 → supprime
⚠️ Pièges fréquents
  • PUT vs PATCH : PUT remplace toute la ressource, PATCH ne modifie que les champs envoyés. Confondre les deux casse la sémantique REST.
  • Réponds 201 Created pour POST, 200 OK pour GET/PUT/PATCH, 204 No Content pour DELETE (pas de body).
💡 Astuce

Une fois le CRUD en place pour une ressource, tu peux le reproduire pour toutes les autres (products, articles, orders...) en changeant juste les noms.

JS - Fiche originale

Fiche 274 - Validation des donnees
💡 En clair

La validation vérifie les données reçues avant de les traiter. Elle empêche les données invalides d'atteindre la base, et protège contre les injections et les incohérences.

📖 Mots à connaître
validationvérifier que les données sont conformes aux règles
Joibibliothèque de validation par schéma
express-validatormiddleware de validation intégré aux routes Express
Zodalternative moderne à Joi, avec inférence de types TypeScript
JS
// Avec Joi
const Joi = require("joi");

const schema = Joi.object({
  nom: Joi.string().min(2).max(50).required(),
  email: Joi.string().email().required(),
  age: Joi.number().integer().min(0).max(120)
});

async function create(data) {
  const { error, value } = schema.validate(data);
  if (error) throw new Error(error.details[0].message);
  return await userRepository.create(value);
}

Avec express-validator directement dans la route :

JS
const { body, validationResult } = require("express-validator");

router.post("/users",
  body("email").isEmail().withMessage("Email invalide"),
  body("nom").isLength({ min: 2 }).withMessage("Nom trop court"),
  (req, res) => {
    const erreurs = validationResult(req);
    if (!erreurs.isEmpty()) {
      return res.status(400).json({ erreurs: erreurs.array() });
    }
    // suite du traitement...
  }
);
✏️ Ligne par ligne
Joi.object({ ... })définit un schéma de validation déclaratif
schema.validate(data)renvoie { error, value } — value contient les données validées
body("email").isEmail()middleware express-validator : valide req.body.email
validationResult(req)récupère les erreurs accumulées par les middlewares
return res.status(400).json({ erreurs: ... })400 Bad Request + détail des erreurs
⚠️ Pièges fréquents
  • Ne jamais faire confiance au client : la validation côté navigateur est cosmétique, le serveur doit toujours revalider.
  • Une validation "à la main" (if/else en cascade) devient vite illisible. Préfère Joi, Zod ou express-validator dès qu'il y a plus de 2-3 champs.
💡 Astuce

En pratique : validation technique en route (express-validator), validation métier en service (Joi ou Zod). Les deux se complètent.

JS - Fiche originale

Fiche 275 - Gestion centralisee des erreurs
💡 En clair

Plutôt que d'écrire try/catch dans chaque controller, on centralise la gestion dans un middleware d'erreur unique. Plus propre, plus lisible, une seule façon de formater les erreurs.

📖 Mots à connaître
middleware d'erreurfonction à 4 paramètres (err, req, res, next) reconnue par Express
AppErrorclasse d'erreur personnalisée avec un code HTTP (404, 400, 409...)
asyncHandlerwrapper qui attrape les erreurs async et les passe à next()
JS
// errors/AppError.js
class AppError extends Error {
  constructor(message, status = 400) {
    super(message);
    this.status = status;
  }
}
module.exports = AppError;

// middlewares/errorHandler.js
function errorHandler(err, req, res, next) {
  console.error(err);
  res.status(err.status || 500).json({
    erreur: err.message || "Erreur serveur"
  });
}
module.exports = errorHandler;

// app.js — branché EN DERNIER
app.use("/users", userRoutes);
app.use(errorHandler); // après toutes les routes !

Le service lance l'erreur, le middleware la transforme en réponse :

JS
// services/userService.js
const AppError = require("../errors/AppError");

async function getById(id) {
  const user = await userRepository.findById(id);
  if (!user) throw new AppError("Utilisateur introuvable", 404);
  return user;
}
✏️ Ligne par ligne
class AppError extends Errorerreur personnalisée avec un status HTTP
this.status = statusle code HTTP associé (404, 400, 409...)
function errorHandler(err, req, res, next)4 paramètres — Express reconnaît un middleware d'erreur
res.status(err.status || 500).json(...)réponse JSON uniforme pour TOUTES les erreurs
app.use(errorHandler)branché en DERNIER pour capter toutes les erreurs
⚠️ Pièges fréquents
  • Un middleware d'erreur doit avoir exactement 4 paramètres : (err, req, res, next). Avec 3, Express ne le reconnaît pas comme middleware d'erreur.
  • Express 4 n'attrape pas les erreurs des fonctions async — il faut un wrapper asyncHandler ou Express 5.
💡 Astuce

Wrapper async standard : const asyncHandler = fn => (req, res, next) => Promise.resolve(fn(req, res, next)).catch(next);. Mettez-le dans un utilitaire partagé.

JS - Fiche originale

Fiche 276 - Variables d'environnement backend
💡 En clair

Dans un backend, les variables d'environnement servent à externaliser toute la configuration sensible : connexion BDD, clé JWT, clés d'API Stripe/Google, ports, mode dev/prod.

📖 Mots à connaître
.envfichier texte à la racine — paires CLE=valeur, jamais commit
.env.exampleversion sans vraies valeurs — versionnée comme documentation
dotenvpaquet qui charge .env dans process.env
NODE_ENVconvention : "development" ou "production" — change le comportement d'Express
JS
# .env
PORT=3000
NODE_ENV=development
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=secret123
DB_NAME=monapp
JWT_SECRET=uneCleTresLongueEtSecrete
JWT_EXPIRES=7d

Chargement et vérification au démarrage :

JS
// app.js (tout en haut)
require("dotenv").config();
const express = require("express");

// Vérifier les variables obligatoires
const obligatoires = ["DB_HOST", "DB_USER", "DB_PASSWORD", "JWT_SECRET"];
for (const cle of obligatoires) {
  if (!process.env[cle]) {
    console.error(`Variable manquante : ${cle}`);
    process.exit(1);
  }
}

const PORT = process.env.PORT || 3000;
const app = express();
app.listen(PORT, () => console.log(`Serveur sur :${PORT}`));
Terminal
$ node app.js
Serveur sur :3000
✏️ Ligne par ligne
require("dotenv").config()charge .env dans process.env — à mettre TOUT EN HAUT
for (const cle of obligatoires)vérifie que chaque variable obligatoire est définie
process.exit(1)quitte en erreur si une variable manque — échec rapide
process.env.PORT || 3000valeur par défaut si PORT n'est pas défini
⚠️ Pièges fréquents
  • Ne JAMAIS committer .env — tes secrets finissent sur GitHub visibles par tout le monde. Ajoute-le au .gitignore.
  • En production, les variables sont souvent injectées par le système (Docker, Kubernetes, PM2, Vercel...) — pas de fichier .env sur le serveur.
💡 Astuce

Versionne un .env.example avec les mêmes clés mais des valeurs vides. Les nouveaux développeurs le copient en .env et remplissent leurs valeurs.

JS - Fiche originale

Fiche 277 - Connexion a une base de donnees
💡 En clair

Pour connecter Express à une base de données, on utilise une bibliothèque adaptée au type de BDD : Mongoose pour MongoDB, pg pour PostgreSQL, mysql2 pour MySQL, sequelize/Prisma comme ORM multi-BDD.

📖 Mots à connaître
mongooseODM pour MongoDB — schémas, validations, middlewares
pgpilote PostgreSQL — Pool de connexions, requêtes SQL
mysql2pilote MySQL avec support des Promises
sequelize / PrismaORM multi-BDD — abstraction SQL complète
JS
// config/database.js — MongoDB avec Mongoose
const mongoose = require("mongoose");

async function connect() {
  try {
    await mongoose.connect(process.env.MONGO_URI);
    console.log("MongoDB connecté");
  } catch (err) {
    console.error("Erreur MongoDB :", err.message);
    process.exit(1);
  }
}

module.exports = { connect };

Avec PostgreSQL (pg) :

JS
// config/database.js — PostgreSQL avec pg
const { Pool } = require("pg");

const pool = new Pool({
  host: process.env.DB_HOST,
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME,
  port: 5432
});

async function query(sql, params) {
  const result = await pool.query(sql, params);
  return result.rows;
}

module.exports = { query };
✏️ Ligne par ligne
mongoose.connect(process.env.MONGO_URI)attend la connexion à MongoDB
new Pool({ ... })crée un pool de connexions réutilisables
pool.query(sql, params)exécute une requête SQL paramétrée
process.exit(1)si la connexion échoue au démarrage, on quitte — inutile de continuer
⚠️ Pièges fréquents
  • Crée une seule connexion partagée dans toute l'app. Ne pas ouvrir une connexion par requête — ça épuise les ressources de la BDD.
  • Toujours gérer l'échec de connexion au démarrage : try/catch + process.exit(1). Sinon, l'app tourne mais toutes les requêtes échouent.
💡 Astuce

Pour fermer proprement à l'arrêt : process.on("SIGINT", async () => { await mongoose.connection.close(); process.exit(0); }). Utile en production.

JS - Fiche originale

Fiche 278 - Authentification
💡 En clair

L'authentification vérifie qui est l'utilisateur ("Qui es-tu ?"). C'est l'étape du login : prouver son identité, généralement avec email + mot de passe. Le serveur renvoie ensuite un token (JWT).

📖 Mots à connaître
hashtransformation irréversible d'un mot de passe — ne jamais stocker en clair
bcryptbibliothèque standard pour hasher les mots de passe
saltchaîne aléatoire ajoutée au mot de passe avant hash — protège contre les rainbow tables
JWTJSON Web Token — preuve d'identité transportée par le client
JS
// Inscription : hasher puis stocker
const bcrypt = require("bcrypt");

async function inscription(data) {
  const existant = await userRepository.findByEmail(data.email);
  if (existant) throw new AppError("Email déjà utilisé", 409);

  const hash = await bcrypt.hash(data.password, 10);
  return await userRepository.create({
    nom: data.nom,
    email: data.email,
    password: hash
  });
}

// Connexion : vérifier puis émettre un token
async function connexion(email, password) {
  const user = await userRepository.findByEmail(email);
  if (!user) throw new AppError("Identifiants invalides", 401);

  const valide = await bcrypt.compare(password, user.password);
  if (!valide) throw new AppError("Identifiants invalides", 401);

  return genererToken(user); // voir fiche 280}
✏️ Ligne par ligne
bcrypt.hash(data.password, 10)hash avec 10 rounds de salt — protège contre les attaques par dictionnaire
bcrypt.compare(password, user.password)compare le mot de passe saisi avec le hash stocké — revoie true/false
throw new AppError("Identifiants invalides", 401)message identique pour email inconnu OU mauvais mdp — évite l'énumération
genererToken(user)crée un JWT qui prouve l'identité de l'utilisateur
⚠️ Pièges fréquents
  • Ne jamais stocker un mot de passe en clair. Toujours le hasher avec bcrypt (ou argon2).
  • Ne pas renvoyer des messages différents pour "email inconnu" vs "mauvais mot de passe" — ça permettrait à un attaquant d'énumérer les emails valides.
💡 Astuce

Le salt rounds (10 par défaut) ralentit bcrypt. Augmente-le progressivement avec la puissance des machines (12 aujourd'hui, 14 dans quelques années).

JS - Fiche originale

Fiche 279 - Autorisation
💡 En clair

L'autorisation vérifie ce que l'utilisateur a le droit de faire ("Que peux-tu faire ?"). Elle intervient après l'authentification, et repose souvent sur des rôles : user, moderator, admin.

📖 Mots à connaître
rôleétiquette attribuée à un utilisateur : "user", "admin"...
middleware d'autorisationfonction qui vérifie que l'utilisateur a le bon rôle avant de laisser passer
401 Unauthorizedpas authentifié (pas de token valide)
403 Forbiddenauthentifié mais pas autorisé (mauvais rôle)
JS
// middlewares/auth.js (rôles)
function autoriser(...roles) {
  return (req, res, next) => {
    if (!req.user) {
      return res.status(401).json({ erreur: "Non authentifié" });
    }
    if (!roles.includes(req.user.role)) {
      return res.status(403).json({ erreur: "Accès refusé" });
    }
    next();
  };
}

module.exports = autoriser;

// routes/userRoutes.js
// Tous les connectés
router.get("/profil", authMiddleware, userController.profil);

// Admin seulement
router.delete("/users/:id",
  authMiddleware,
  autoriser("admin"),
  userController.supprimer
);
✏️ Ligne par ligne
function autoriser(...roles)fonction qui retourne un middleware — capture les rôles autorisés
if (!req.user) → 401l'utilisateur n'est même pas connecté
if (!roles.includes(req.user.role)) → 403connecté mais mauvais rôle
autoriser("admin")middleware appliqué sur la route DELETE /users/:id
⚠️ Pièges fréquents
  • 401 ≠ 403. 401 = pas authentifié. 403 = authentifié mais pas autorisé. Mélanger les deux casse la sémantique HTTP.
  • Ne jamais faire confiance au client pour cacher un bouton admin : il faut toujours vérifier le rôle côté serveur dans le middleware.
💡 Astuce

Règle d'autorisation courante : "un utilisateur ne peut modifier que SON propre profil". Vérifie req.user.id === req.params.id dans le controller.

JS - Fiche originale

Fiche 280 - JWT : principe
💡 En clair

JWT (JSON Web Token) est un jeton signé qui prouve l'identité d'un utilisateur. Il est composé de 3 parties : header.payload.signature. Le serveur n'a pas besoin de stocker de session — c'est "stateless".

📖 Mots à connaître
header1re partie — algorithme utilisé (HS256, RS256...)
payload2e partie — les données transportées (id, rôle, expiration)
signature3e partie — preuve que le token est authentique (signé avec JWT_SECRET)
expclaim standard : date d'expiration du token
statelessle serveur ne stocke rien — il vérifie juste la signature
JS
// Structure d'un JWT
eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwicm9sZSI6ImFkbWluIn0.abc123
|--- header ---|--- payload ---|--- signature ---|

// Payload décodé (base64) :
{
  "id": 1,
  "role": "admin",
  "iat": 1700000000,
  "exp": 1700604800
}

Créer et vérifier un token avec jsonwebtoken :

JS
const jwt = require("jsonwebtoken");

// Créer un token (à la connexion)
function genererToken(user) {
  return jwt.sign(
    { id: user.id, role: user.role },
    process.env.JWT_SECRET,
    { expiresIn: "7d" }
  );
}

// Vérifier un token (à chaque requête protégée)
function verifierToken(token) {
  try {
    return jwt.verify(token, process.env.JWT_SECRET);
  } catch (err) {
    return null; // token invalide ou expiré
  }
}
✏️ Ligne par ligne
jwt.sign({ id, role }, secret, { expiresIn })crée un token signé avec une durée de vie
{ id: user.id, role: user.role }le payload — ce qu'on transporte dans le token
process.env.JWT_SECRETla clé secrète utilisée pour signer — jamais exposée
jwt.verify(token, secret)vérifie la signature et renvoie le payload décodé
⚠️ Pièges fréquents
  • Le payload est encodé en base64, pas chiffré. Ne JAMAIS y mettre de données sensibles (mot de passe, carte bancaire...).
  • Sans JWT_SECRET solide (32+ caractères aléatoires), un attaquant peut forger des tokens valides.
💡 Astuce

Inconvénient du JWT : impossible à révoquer avant expiration. Pour y palier : blacklist en Redis, tokens courts (15 min) + refresh token, ou fallback session côté serveur.

JS - Fiche originale

Fiche 281 - Middleware d'authentification
💡 En clair

Le middleware d'authentification vérifie le JWT envoyé par le client à chaque requête protégée. Si le token est valide, il attache l'utilisateur à req.user et laisse passer. Sinon, il renvoie 401.

📖 Mots à connaître
Authorization headerheader HTTP : Authorization: Bearer <token>
Bearerpréfixe standard indiquant un token d'authentification
req.userobjet attaché par le middleware — contient id, rôle...
next()fonction qui passe au middleware ou au controller suivant
JS
// middlewares/auth.js
const jwt = require("jsonwebtoken");

function authMiddleware(req, res, next) {
  const header = req.headers.authorization;
  if (!header) {
    return res.status(401).json({ erreur: "Token manquant" });
  }

  const token = header.split(" ")[1]; // "Bearer xxx" → "xxx"
  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    req.user = decoded; // attache l'utilisateur à la requête
    next(); // laisse passer
  } catch (err) {
    return res.status(401).json({ erreur: "Token invalide" });
  }
}

module.exports = authMiddleware;

// Utilisation dans les routes
router.get("/profil", authMiddleware, userController.profil);
router.delete("/users/:id",
  authMiddleware,         // 1. authentifié
  autoriser("admin"),     // 2. autorisé
  userController.supprimer // 3. exécuté
);
Terminal
$ curl -H "Authorization: Bearer eyJhbG..." http://localhost:3000/profil
{"id":1,"nom":"Awa","email":"a@b.com"}
✏️ Ligne par ligne
req.headers.authorizationrécupère le header "Authorization: Bearer xxx"
header.split(" ")[1]extrait le token en supprimant le préfixe "Bearer "
jwt.verify(token, JWT_SECRET)vérifie signature + expiration → renvoie le payload
req.user = decodedattache l'utilisateur à req.user pour les middlewares suivants
next()passe la main au middleware/controller suivant
⚠️ Pièges fréquents
  • Si le header Authorization est absent → 401. Si le token est invalide (signature incorrecte, expiré) → 401. Ne jamais renvoyer 200 par défaut.
  • L'ordre des middlewares compte : authMiddleware d'abord, autoriser("admin") ensuite, controller en dernier. Sinon, req.user n'existera pas quand l'autorisation cherchera le rôle.
💡 Astuce

Pour protéger tout un groupe de routes : router.use(authMiddleware) en haut du router. Toutes les routes en dessous héritent de la protection.