Cours JavaScript Complet ⚡

Les 12 chapitres essentiels — des bases au JavaScript moderne (ES6+), avec exemples et quiz

12
Chapitres
100+
Exemples de code
ES2024
Standard
A1→C2
Niveaux

CHAPITRE 01

Variables et types de données

📦 let, const et var
// const — valeur qui ne sera pas réassignée (à privilégier)
const PI = 3.14159;
const nom = « Alice »;

// let — valeur qui peut être réassignée
let age = 25;
age = 26; // ✅ OK

// var — ancienne syntaxe, à ÉVITER
var ancien = « ne plus utiliser »; // ❌

Règle d'or : Utilisez const par défaut. Passez à let uniquement si la valeur doit changer. N'utilisez jamais var — il a des comportements imprévisibles (hoisting, pas de block scope).

🔢 Les types primitifs
Type Description Exemple typeof
string Chaîne de caractères « hello », 'world', `template` « string »
number Entier ou décimal 42, 3.14, NaN, Infinity « number »
bigint Très grands entiers 9007199254740991n « bigint »
boolean Vrai / Faux true, false « boolean »
undefined Variable déclarée sans valeur let x; « undefined »
null Absence intentionnelle de valeur null « object » ⚠️
symbol Identifiant unique Symbol(« id ») « symbol »

Piège historique : typeof null retourne « object » — c'est un bug connu depuis 1995 qui n'a jamais été corrigé. Pour tester null, utilisez x === null.

📝 Template literals (backticks)
const nom = « Alice »;
const age = 25;

// Template literal avec backticks ` `
console.log(`Je m'appelle $ et j'ai $ ans.`);
console.log(`Dans 5 ans : $ ans.`);

// Multi-lignes
const html = `

$

Âge : $

`;

🔄 Conversion de types
// Conversion explicite
Number(« 42 ») // 42
Number(« hello ») // NaN
String(42) // « 42 »
Boolean(0) // false
Boolean(«  ») // false
Boolean(« hello ») // true
parseInt(« 42px ») // 42 (ignore le reste)
parseFloat(« 3.14 ») // 3.14

// Coercion implicite (piège JS !)
« 5 » + 3 // « 53 » (string concat !)
« 5 » 3 // 2 (conversion auto en number)
« 5 » * 3 // 15
true + 1 // 2

Le piège le plus courant en JS : « 5 » + 3 = « 53 » (concaténation) mais « 5 » – 3 = 2 (soustraction). L'opérateur + privilégie la concaténation si un opérande est un string.

🧠 Quiz
Que donne typeof null ?
« object » — Bug historique de JavaScript. Pour tester null : x === null.
Que donne « 10 » + 5 ?
« 105 » — Le + avec un string fait une concaténation. Pour additionner : Number("10") + 5 → 15.

CHAPITRE 02

Opérateurs et expressions

⚖️ == vs === (la question la plus importante en JS)
// == (égalité lâche) — convertit les types avant de comparer
5 == « 5 » // true ⚠️ (conversion implicite)
0 == false // true ⚠️
«  » == false // true ⚠️
null == undefined // true ⚠️

// === (égalité stricte) — compare type ET valeur
5 === « 5 » // false ✅
0 === false // false ✅
null === undefined // false ✅

Règle absolue : Utilisez TOUJOURS === et !==. N'utilisez JAMAIS == et !=. Les conversions implicites de == causent des bugs subtils et imprévisibles.

🔗 Opérateurs logiques et nullish
// Logiques classiques
true && false // false (ET)
true || false // true (OU)
!true // false (NON)

// Short-circuit — retourne la valeur, pas un booléen
« Alice » || « Bob » // « Alice » (premier truthy)
«  » || « Bob » // « Bob » (premier truthy)
« Alice » && « Bob » // « Bob » (dernier truthy)
«  » && « Bob » // «  » (premier falsy)

// ?? (nullish coalescing) — seulement null/undefined
null ?? « défaut » // « défaut »
undefined ?? « défaut » // « défaut »
0 ?? « défaut » // 0 (0 n'est PAS null)
«  » ?? « défaut » // «  » (vide n'est PAS null)

// ?. (optional chaining)
const user = ;
user?.address?.city // « Paris »
user?.phone?.number // undefined (pas d'erreur !)

|| vs ?? : || traite toutes les valeurs falsy (0, «  », false, null, undefined). ?? ne traite QUE null et undefined. Utilisez ?? quand 0 ou «  » sont des valeurs valides.

🔗 Opérations sur les strings
const s = « Hello, World! »;
s.length // 13 (propriété, pas méthode)
s.toUpperCase() // « HELLO, WORLD! »
s.toLowerCase() // « hello, world! »
s.trim() // Supprime espaces début/fin
s.includes(« World ») // true
s.startsWith(« He ») // true
s.indexOf(« World ») // 7 (-1 si absent)
s.replace(« World », « JS ») // « Hello, JS! »
s.split(« , « ) // [« Hello », « World! »]
s.slice(0, 5) // « Hello »
s.repeat(3) // « Hello, World!Hello, World!Hello, World! »
s.padStart(20, « * ») // « *******Hello, World! »
🧠 Quiz
Que donne 0 || « default » vs 0 ?? « default » ?
« default » vs 0. || traite 0 comme falsy → retourne « default ». ?? ne réagit qu'à null/undefined → retourne 0.

CHAPITRE 03

Structures conditionnelles

🔀 if / else if / else
const age = 18;

if (age < 13) else if (age < 18) else if (age < 65) else

⚡ Ternaire et switch
// Ternaire
const statut = age >= 18 ? « majeur » : « mineur »;

// Switch
switch (jour)

N'oubliez pas le break ! Sans break, le switch continue d'exécuter les cases suivants (fall-through). C'est le piège n°1 du switch en JS.

🔍 Valeurs falsy en JavaScript

Il y a exactement 7 valeurs falsy en JS — tout le reste est truthy :

false // le booléen false
0 // le nombre zéro (et -0)
«  » // string vide
null // absence de valeur
undefined // variable non assignée
NaN // Not a Number
0n // BigInt zéro

// ⚠️ Truthy surprenants :
Boolean(« false ») // true ! (string non vide)
Boolean(« 0 ») // true ! (string non vide)
Boolean([]) // true ! (array vide = truthy en JS)
Boolean() // true ! (objet vide = truthy en JS)

Différence Python/JS : En Python, [] et sont falsy. En JavaScript, tous les objets et arrays sont truthy, même vides. Pour tester un array vide : arr.length === 0.

CHAPITRE 04

Les boucles

🔁 for, for…of, for…in
// for classique
for (let i = 0; i < 5; i++)

// for…of — itère sur les VALEURS (arrays, strings, Map, Set)
const fruits = [« pomme », « banane », « cerise »];
for (const fruit of fruits)

// for…in — itère sur les CLÉS d'un objet
const personne = ;
for (const cle in personne)

for…of vs for…in : for…of = valeurs (pour les arrays). for…in = clés/index (pour les objets). N'utilisez PAS for...in sur un array (il itère aussi sur les propriétés du prototype).

🔄 while + do…while
// while
let i = 0;
while (i < 5)

// do…while — s'exécute AU MOINS une fois
let j = 10;
do while (j < 5);

// break et continue fonctionnent comme en Python

🧠 Quiz
for…of itère sur les valeurs ou les clés ?
Les valeurs. for…of = valeurs (arrays, strings). for…in = clés/propriétés (objets).

CHAPITRE 05

Les fonctions

🔧 Trois façons de déclarer une fonction
// 1. Déclaration classique (hoisted — utilisable avant sa déclaration)
function saluer(nom) {
return `Bonjour, $ !`;
}

// 2. Expression de fonction
const saluer2 = function(nom) {
return `Bonjour, $ !`;
};

// 3. Arrow function (ES6+) — syntaxe moderne recommandée
const saluer3 = (nom) => `Bonjour, $ !`;

// Arrow : si un seul paramètre, pas besoin de ()
const double = x => x * 2;

// Arrow : si plusieurs lignes, et return explicite
const somme = (a, b) => ;

📦 Paramètres par défaut, rest et spread
// Paramètres par défaut
const puissance = (base, exp = 2) => base ** exp;
puissance(3); // 9
puissance(3, 3); // 27

// Rest parameter (…) — comme *args en Python
const somme = (nombres) => ;
somme(1, 2, 3); // 6

// Spread operator — décomposer un array/objet
const a = [1, 2];
const b = [a, 3, 4]; // [1, 2, 3, 4]

const obj1 = ;
const obj2 = ; //

⚡ Arrow functions et « this »

Différence cruciale : Les arrow functions n'ont pas leur propre this. Elles héritent du this du contexte parent. C'est un avantage dans les callbacks mais un piège dans les méthodes d'objet :

const personne = ;
🧠 Quiz
Peut-on utiliser une arrow function comme méthode d'objet ?
Non (pas recommandé) — Les arrow functions n'ont pas leur propre this. Dans une méthode, this ne pointera pas vers l'objet. Utilisez la syntaxe courte saluer() .

CHAPITRE 06

Les tableaux (Arrays)

📋 Méthodes de base
const fruits = [« pomme », « banane », « cerise »];

// Accès
fruits[0] // « pomme »
fruits.at(1) // « cerise » (ES2022)
fruits.length // 3

// Ajout / suppression
fruits.push(« kiwi ») // Ajoute à la fin → retourne la longueur
fruits.pop() // Supprime le dernier → retourne l'élément
fruits.unshift(« poire ») // Ajoute au début
fruits.shift() // Supprime le premier

// Recherche
fruits.includes(« banane ») // true
fruits.indexOf(« banane ») // 1 (-1 si absent)
fruits.find(f => f.length > 5) // « banane » (premier match)
fruits.findIndex(f => f === « cerise ») // 2

// Modification
fruits.splice(1, 1) // Supprime 1 élément à l'index 1
fruits.splice(1, 0, « mangue ») // Insère sans supprimer
fruits.slice(0, 2) // Copie [« pomme », »banane »] (non destructif)

⚡ Méthodes fonctionnelles (les plus importantes)
const nombres = [1, 2, 3, 4, 5];

// map — transforme chaque élément → nouveau array
const doubles = nombres.map(n => n * 2);
// [2, 4, 6, 8, 10]

// filter — garde les éléments qui passent le test
const pairs = nombres.filter(n => n % 2 === 0);
// [2, 4]

// reduce — accumule une valeur
const somme = nombres.reduce((acc, n) => acc + n, 0);
// 15

// forEach — exécute une action (pas de retour)
nombres.forEach(n => console.log(n));

// some / every — tests logiques
nombres.some(n => n > 4) // true (au moins un)
nombres.every(n => n > 0) // true (tous)

// Chaînage
const resultat = nombres
.filter(n => n % 2 === 0)
.map(n => n ** 2);
// [4, 16]

map/filter/reduce : Ces trois méthodes sont le cœur de la programmation fonctionnelle en JS. map = transformer, filter = sélectionner, reduce = accumuler. Elles retournent toutes un nouveau array (non destructif).

🔀 Tri, concat, flat
// sort — ATTENTION : trie en tant que strings par défaut ![10, 1, 21, 2].sort() // [1, 10, 2, 21] ❌[10, 1, 21, 2].sort((a, b) => a b) // [1, 2, 10, 21] ✅

// reverse[1, 2, 3].reverse() // [3, 2, 1] (modifie l'original !)[1, 2, 3].toReversed() // [3, 2, 1] (ES2023, non destructif)

// Concaténer / Aplatir[1, 2].concat([3, 4]) // [1, 2, 3, 4][[1, 2], [3, 4]] // [1, 2, 3, 4] (spread)[[1, 2], [3, 4]].flat() // [1, 2, 3, 4]

Piège sort() : Sans comparateur, .sort() convertit tout en string : [10,1,21,2].sort()[1,10,2,21]. Toujours fournir (a, b) => a – b pour les nombres.

🧠 Quiz
Différence entre map() et forEach() ?
map() retourne un nouveau array transformé. forEach() exécute une action mais retourne undefined. Utilisez map quand vous voulez récupérer le résultat.
Que donne [3,1,2].sort() ?
[1, 2, 3] — Ça marche ici car les chiffres à 1 digit se trient correctement en tant que strings. Mais [10,1,2].sort()[1, 10, 2] (piège).

CHAPITRE 07

Les objets

📦 Créer et manipuler des objets
// Objet littéral
const personne = ;

// Accès
personne.nom // « Alice » (dot notation)
personne[« age »] // 25 (bracket notation)
personne.saluer() // « Bonjour, Alice »

// Modification
personne.email = « a@b.com »; // Ajout
delete personne.ville; // Suppression

// Vérification
« nom » in personne // true
personne.hasOwnProperty(« age ») // true

// Itérer
Object.keys(personne) // [« nom », « age », « email », « saluer »]
Object.values(personne) // [« Alice », 25, « a@b.com », ƒ]
Object.entries(personne) // [[« nom », »Alice »], [« age »,25], …]

⚡ Destructuration (ES6+)
// Destructuration d'objet
const = personne;
console.log(nom); // « Alice »
console.log(ville); // « Inconnu » (valeur par défaut)

// Renommer pendant la destructuration
const = personne;

// Destructuration d'array
const [premier, deuxieme, reste] = [1, 2, 3, 4, 5];
// premier = 1, deuxieme = 2, reste = [3, 4, 5]

// Dans les paramètres de fonction
const afficher = () => {
console.log(`$ a $ ans`);
};
afficher(personne);

La destructuration est partout en JS moderne. Elle simplifie l'extraction de données dans les fonctions, les imports, les réponses d'API, les props React, etc.

🔄 Copie d'objets (shallow vs deep)
const original = ;

// ❌ Pas une copie — même référence
const ref = original;

// Shallow copy (copie superficielle)
const copie1 = ;
const copie2 = Object.assign(, original);

// ⚠️ Les objets imbriqués sont toujours des références
copie1.b.c = 99;
console.log(original.b.c); // 99 ! (modifié aussi)

// Deep copy (copie profonde)
const deep = structuredClone(original); // ES2022 ✅
const deep2 = JSON.parse(JSON.stringify(original)); // Ancien hack

🧠 Quiz
Que fait si les deux ont une clé « nom » ?
La valeur de obj2 écrase celle de obj1. Le dernier spread gagne (comme les propriétés plus à droite).

CHAPITRE 08

Les classes (POO)

🏛️ Syntaxe des classes (ES6+)
class Animal

const rex = new Animal(« Rex », 5);
rex.parler() // « Rex fait du bruit. »
rex.info // « Rex (5 ans) » — getter, pas de ()

🔗 Héritage et champs privés
class Chien extends Animal

const max = new Chien(« Max », 3, « Labrador »);
max.parler() // « Max : Wouf ! »
max.race // « Labrador » (via getter)
max.#race // ❌ SyntaxError (privé)
max instanceof Chien // true
max instanceof Animal // true

🧠 Quiz
À quoi sert super() dans un constructeur enfant ?
Il appelle le constructeur parent. Obligatoire avant d'utiliser this dans une classe qui extends.

CHAPITRE 09

Asynchrone : Promises & async/await

⏱️ Pourquoi l'asynchrone ?

JavaScript est single-threaded. Les opérations longues (réseau, timers, fichiers) sont asynchrones pour ne pas bloquer l'interface.

Évolution : Callbacks (ancien) → Promises (ES6) → async/await (ES2017, recommandé).

🤝 Promises
const maPromise = new Promise((resolve, reject) => );

maPromise
.then(data => console.log(data))
.catch(err => console.error(err))
.finally(() => console.log(« Terminé »));

// Combinateurs
Promise.all([p1, p2]) // Toutes résolues (échoue si une échoue)
Promise.allSettled([p1, p2]) // Attend toutes (peu importe succès/échec)
Promise.race([p1, p2]) // La première terminée
Promise.any([p1, p2]) // La première résolue

⚡ async / await
async function fetchUser(id)

// Arrow async
const getData = async () => ;

// Parallèle avec async/await
const [users, posts] = await Promise.all([
fetch(« /api/users »).then(r => r.json()),
fetch(« /api/posts »).then(r => r.json())
]);

Piège fetch() : fetch() ne rejette PAS sur un 404 ou 500. Il faut vérifier response.ok manuellement. La Promise ne rejette que sur une erreur réseau.

🧠 Quiz
fetch() rejette-t-il sur un 404 ?
Non. fetch rejette uniquement sur erreur réseau. Un 404 donne response.ok === false mais la Promise est résolue.

CHAPITRE 10

Manipulation du DOM

🎯 Sélectionner des éléments
document.querySelector(« .classe ») // Premier match
document.querySelectorAll(« .classe ») // Tous (NodeList)
document.querySelector(« #id ») // Par ID
document.querySelector(« div > p.active ») // CSS selector
✏️ Modifier contenu, classes et style
const el = document.querySelector(« #titre »);

// Contenu
el.textContent = « Texte »; // Texte brut (sûr)
el.innerHTML = « HTML »; // HTML (⚠️ XSS)

// Classes
el.classList.add(« active »);
el.classList.remove(« hidden »);
el.classList.toggle(« dark »);
el.classList.contains(« active »);

// Style
el.style.color = « red »;
el.style.fontSize = « 20px »; // camelCase !

// Attributs
el.setAttribute(« data-id », « 42 »);
el.getAttribute(« href »);
el.dataset.id // « 42 » (accès data-* attributes)

🎧 Événements
const btn = document.querySelector(« #btn »);

btn.addEventListener(« click », (e) => );

// Événements courants :
// click, dblclick, mouseover, mouseout
// keydown, keyup, input, change
// submit, focus, blur, scroll, resize
// DOMContentLoaded, load

// Event delegation (1 listener pour N enfants)
document.querySelector(« ul »)
.addEventListener(« click », (e) => );

🔨 Créer et supprimer
const div = document.createElement(« div »);
div.textContent = « Nouveau ! »;
div.classList.add(« card »);

parent.appendChild(div); // À la fin
parent.prepend(div); // Au début
element.after(div); // Après
div.remove(); // Suppression

🧠 Quiz
Différence entre textContent et innerHTML ?
textContent = texte brut (sûr). innerHTML = HTML parsé (risque XSS). Préférez textContent.

CHAPITRE 11

Gestion des erreurs

🛡️ try / catch / finally
try catch (error) finally

// Lever une erreur
function diviser(a, b)

// Erreur personnalisée
class ValidationError extends Error

🔥 Types d'erreurs
Erreur Cause Exemple
ReferenceError Variable inexistante console.log(xyz)
TypeError Mauvais type / null access null.toString()
SyntaxError Code mal formé JSON.parse(« {« )
RangeError Hors limites new Array(-1)
URIError URI malformée decodeURI(« % »)

CHAPITRE 12

ES6+ et fonctionnalités modernes

📦 Modules (import / export)
// math.js
export const PI = 3.14159;
export function carre(x)
export default function somme(a, b)

// main.js
import somme from « ./math.js »; // default
import from « ./math.js »; // named
import from « ./math.js »; // alias
import * as math from « ./math.js »; // tout

🗺️ Map et Set
// Map — clé/valeur (clés de n'importe quel type)
const map = new Map();
map.set(« nom », « Alice »);
map.set(42, « réponse »); // Clé = number
map.get(« nom »); // « Alice »
map.has(42); // true
map.size; // 2
map.delete(42);

for (const [key, val] of map)

// Set — valeurs uniques
const set = new Set([1, 2, 2, 3]); //
set.add(4);
set.has(2); // true
set.delete(2);
set.size; // 3

// Dédupliquer un array
const unique = [new Set([1,1,2,3,3])]; // [1, 2, 3]

Map vs Object : Map accepte n'importe quel type comme clé (objets, fonctions, etc.), préserve l'ordre d'insertion et a une propriété .size. Préférez Map pour les dictionnaires dynamiques.

⚡ Fonctionnalités récentes (ES2020–2024)
Feature Version Exemple
?? nullish coalescing ES2020 null ?? « défaut »« défaut »
?. optional chaining ES2020 user?.address?.city
??= logical assignment ES2021 x ??= 5 (assigne si null/undefined)
.at() ES2022 [1,2,3].at(-1)3
#private fields ES2022 class
structuredClone() ES2022 Deep copy d'objets
.toReversed() ES2023 Reverse non destructif
.toSorted() ES2023 Sort non destructif
.with() ES2023 [1,2,3].with(1, 99)[1,99,3]
Object.groupBy() ES2024 Grouper des éléments par critère
🔧 Bonnes pratiques récap

✅ À FAIRE
const par défaut, let si nécessaire
• Toujours ===
• Arrow functions pour les callbacks
• Destructuration pour extraire des données
?? au lieu de || pour les défauts
async/await + try/catch
• Template literals au lieu de concaténation

❌ À ÉVITER
var (hoisting imprévisible)
== et != (coercion)
for…in sur les arrays
arguments (utiliser …rest)
• Mutation directe des arrays/objets
• .sort() sans comparateur sur les nombres
• Arrow functions comme méthodes d'objet

🧠 Quiz
Comment dédupliquer un array [1,1,2,3,3] en une ligne ?
[…new Set([1,1,2,3,3])][1, 2, 3]. Le Set supprime les doublons, le spread le reconvertit en array.
Différence entre .sort() et .toSorted() ?
.sort() modifie l'array original (destructif). .toSorted() (ES2023) retourne un nouveau array trié sans toucher à l'original.

Cours JavaScript Complet — Des bases à l'ES2024

Pour aller plus loin : MDN Web Docs (la référence officielle).