# 520 Exercices JavaScript Complets - De Débutant à Expert

Guide d'utilisation :

- Chaque chapitre contient 10 exercices progressifs
- Les exercices explorent toutes les fonctionnalités du sujet traité
- Faites les exercices dans l'ordre pour une progression optimale
- N'hésitez pas à tester et modifier votre code

## [LIGHT_BLUE_HEART] PARTIE 1 — Les Fondamentaux (Débutant total)

---

### **Chapitre 1 — Introduction à JavaScript**

**Exercice 1.1** - Premier contact  
Écris un programme qui affiche "Bienvenue dans le monde de JavaScript !" dans la console. Utilise `console.log()`.

**Exercice 1.2** - Affichage multiple  
Crée un programme qui affiche 5 lignes différentes : ton prénom, ton âge, ta ville, ton pays et ta couleur préférée. Chaque information sur une ligne séparée.

**Exercice 1.3** - Commentaires  
Écris un programme qui affiche "JavaScript est génial" et ajoute au moins 3 commentaires dans ton code pour expliquer ce que tu fais. Utilise `//` pour les commentaires sur une ligne et `/* */` pour les commentaires multiligne.

**Exercice 1.4** - Alert et console  
Utilise `alert()` pour afficher un message dans une popup du navigateur. Utilise `console.log()`, `console.warn()`, et `console.error()` pour afficher différents types de messages dans la console.

**Exercice 1.5** - Calculs simples avec console  
Affiche directement le résultat de 15 + 27, 100 - 35, 12 * 8 et 144 / 12 avec `console.log()`. Affiche aussi le texte expliquant chaque opération.

**Exercice 1.6** - Opérateurs spéciaux  
Teste et affiche les résultats de : 10 % 3 (modulo), 2 ** 5 (puissance), 10 / 3 (division), Math.floor(10 / 3) (division entière).

**Exercice 1.7** - Chaînes de caractères  
Crée un programme qui affiche : une citation entre guillemets, un texte avec concaténation `+`, et un texte avec template literals (backticks `).

**Exercice 1.8** - Répétition avec console  
Utilise une boucle simple pour afficher 10 fois le symbole "*" sur des lignes séparées, puis affiche "JavaScript" répété 5 fois verticalement.

**Exercice 1.9** - Type de données  
Crée différentes variables : number, string, boolean, undefined, null. Affiche chaque variable et son type avec `typeof`.

**Exercice 1.10** - Programme interactif basique  
Écris un programme qui demande le nom de l'utilisateur avec `prompt()`, puis affiche "Bonjour [nom] !" avec `alert()` ou `console.log()`.

---

### **Chapitre 2 — Variables et types de données**

**Exercice 2.1** - Déclaration de variables  
Crée des variables avec `var`, `let` et `const`. Explique la différence entre chacune. Crée 5 variables : `nom` (string), `age` (number), `taille` (number), `estEtudiant` (boolean), et `ville` (string).

**Exercice 2.2** - Opérations arithmétiques  
Crée deux variables `a = 45` et `b = 12`. Calcule et affiche : leur somme, différence, produit, division, modulo `%`, et `a` à la puissance `b` (utilise `**`).

**Exercice 2.3** - Conversion de types  
Crée une variable `nombreTexte = "123"`. Convertis-la en number avec `Number()`, `parseInt()`, et `parseFloat()`. Crée une variable `prix = 45.99` et convertis-la en string avec `String()` et `.toString()`.

**Exercice 2.4** - Calcul de moyenne  
Demande à l'utilisateur d'entrer 3 notes (utilise `prompt()` et convertis en number). Calcule et affiche la moyenne de ces trois notes avec 2 décimales (utilise `.toFixed(2)`).

**Exercice 2.5** - Opérations sur variables  
Crée une variable `compteur = 0`. Incrémente-la avec `++`, décrémente avec `--`, utilise `+=`, `-=`, `*=`, `/=`. Affiche la valeur à chaque étape.

**Exercice 2.6** - NaN et Infinity  
Teste et affiche les résultats de : `0 / 0` (NaN), `10 / 0` (Infinity), `"texte" * 2` (NaN). Utilise `isNaN()` et `isFinite()` pour vérifier ces valeurs.

**Exercice 2.7** - Types booléens et comparaisons  
Teste et affiche : `5 > 3`, `10 === "10"`, `10 == "10"`, `null == undefined`, `null === undefined`. Explique la différence entre `==` et `===`.

**Exercice 2.8** - Truthy et Falsy  
Teste quelles valeurs sont truthy ou falsy : `0`, `""`, `null`, `undefined`, `NaN`, `false`, `"0"`, `[]`, `{}`. Utilise `Boolean()` ou des conditions `if`.

**Exercice 2.9** - Calcul d'aire et périmètre  
Demande à l'utilisateur la longueur et la largeur d'un rectangle. Calcule et affiche le périmètre et l'aire. Fais de même pour un cercle (demande le rayon, utilise `Math.PI`).

**Exercice 2.10** - Conversion température  
Demande une température en Celsius. Convertis-la en Fahrenheit (formule : F = C * 9/5 + 32) et en Kelvin (formule : K = C + 273.15). Affiche les trois valeurs avec messages clairs.

---

### **Chapitre 3 — Chaînes de caractères (strings)**

**Exercice 3.1** - Manipulation basique  
Crée une variable `phrase = "javascript est génial"`. Affiche cette phrase en majuscules avec `.toUpperCase()`, en minuscules avec `.toLowerCase()`, et longueur avec `.length`.

**Exercice 3.2** - Indexation et accès  
Crée `mot = "Programmation"`. Affiche le premier caractère `[0]`, le dernier `[mot.length - 1]`, le 5ème caractère, et la longueur totale.

**Exercice 3.3** - Slicing avec substring  
Avec `texte = "Apprendre JavaScript est amusant"`, extrais et affiche : les 9 premiers caractères avec `.substring()`, les 6 derniers, du caractère 10 à 20 avec `.slice()`.

**Exercice 3.4** - Méthodes de recherche  
Crée `phrase = "Je code en JavaScript et j'adore JavaScript"`. Utilise `.indexOf()` pour trouver la position de "JavaScript", `.lastIndexOf()` pour la dernière occurrence, et `.includes()` pour vérifier la présence.

**Exercice 3.5** - Split et Join  
Crée `phrase = "rouge,vert,bleu,jaune"`. Utilise `.split(',')` pour séparer en tableau. Puis utilise `.join(' - ')` pour reformer une chaîne avec " - " comme séparateur.

**Exercice 3.6** - Remplacement  
Crée `texte = "J'aime les bananes et les bananes sont délicieuses"`. Remplace "bananes" par "pommes" avec `.replace()` (première occurrence) et `.replaceAll()` (toutes les occurrences).

**Exercice 3.7** - Trim et espaces  
Crée `texte = "   JavaScript   "`. Utilise `.trim()` pour enlever les espaces au début et à la fin, `.trimStart()` pour seulement à gauche, `.trimEnd()` pour seulement à droite.

**Exercice 3.8** - StartsWith et EndsWith  
Crée plusieurs chaînes et teste avec : `.startsWith()`, `.endsWith()`. Exemple : vérifie si une URL commence par "https://" ou se termine par ".com".

**Exercice 3.9** - Template literals  
Crée des variables `nom = "Marie"`, `age = 25`, `ville = "Paris"`. Utilise les template literals (backticks) pour créer : \`Je m'appelle ${nom}, j'ai ${age} ans\`. Ajoute des calculs : \`Dans 5 ans, j'aurai ${age + 5} ans\`.

**Exercice 3.10** - Répétition et padding  
Utilise `.repeat(3)` pour répéter une chaîne. Utilise `.padStart(10, '0')` pour ajouter des zéros à gauche (exemple : "007"), et `.padEnd(10, '.')` pour ajouter des points à droite.

---

### **Chapitre 4 — Tableaux (arrays)**

**Exercice 4.1** - Création et accès aux tableaux  
Crée un tableau `fruits = ["pomme", "banane", "orange", "kiwi", "mangue"]`. Affiche : le 1er fruit, le dernier, les 3 premiers avec `.slice()`, et la longueur avec `.length`.

**Exercice 4.2** - Modification de tableaux  
Crée `nombres = [10, 20, 30, 40, 50]`. Modifie le 2ème élément en 25, ajoute 60 à la fin avec `.push()`, ajoute 5 au début avec `.unshift()`, supprime le dernier avec `.pop()`.

**Exercice 4.3** - Méthodes de tableaux  
Crée `liste = [3, 1, 4, 1, 5, 9, 2, 6]`. Utilise : `.sort()` pour trier, `.reverse()` pour inverser, `.indexOf(5)` pour trouver la position de 5, `.includes(9)` pour vérifier la présence.

**Exercice 4.4** - Concat et spread  
Crée deux tableaux `tab1 = [1, 2, 3]` et `tab2 = [4, 5, 6]`. Combine-les avec `.concat()`, puis avec l'opérateur spread `[...tab1, ...tab2]`. Compare les deux méthodes.

**Exercice 4.5** - Splice et slice  
Crée `animaux = ["chat", "chien", "oiseau", "poisson", "lapin"]`. Utilise `.splice()` pour supprimer et/ou ajouter des éléments. Utilise `.slice()` pour extraire une portion sans modifier l'original.

**Exercice 4.6** - Join et toString  
Crée un tableau `mots = ["Hello", "World", "JavaScript"]`. Convertis-le en chaîne avec `.join(' ')`, `.join('-')`, et `.toString()`. Compare les résultats.

**Exercice 4.7** - Destructuring  
Crée `point = [100, 200]`. Décompose en variables `let [x, y] = point`. Crée un tableau `valeurs = [1, 2, 3, 4, 5]` et décompose : `let [premier, deuxieme, ...reste] = valeurs`.

**Exercice 4.8** - Fill et copyWithin  
Crée un tableau vide avec `new Array(5)`. Remplis-le avec `.fill(0)`. Utilise `.copyWithin()` pour copier une partie du tableau vers une autre position.

**Exercice 4.9** - Array.from et Array.of  
Utilise `Array.from("Hello")` pour créer un tableau de caractères. Utilise `Array.from({length: 5}, (v, i) => i)` pour créer [0,1,2,3,4]. Utilise `Array.of(1, 2, 3)` pour créer un tableau.

**Exercice 4.10** - Tableaux multidimensionnels  
Crée une matrice 3x3 : `matrice = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]`. Accède à l'élément au centre (5), modifie l'élément en position [0][0], affiche la première ligne, parcours tous les éléments.

---

### **Chapitre 5 — Objets (objects)**

**Exercice 5.1** - Création et accès  
Crée un objet `personne = {nom: "Ahmed", age: 28, ville: "Dakar", profession: "Ingénieur"}`. Accède aux propriétés avec la notation point et la notation crochet. Affiche toutes les clés avec `Object.keys()` et valeurs avec `Object.values()`.

**Exercice 5.2** - Modification et ajout  
Crée `produit = {nom: "Laptop", prix: 800, stock: 15}`. Modifie le prix à 750, ajoute une propriété "marque" avec la valeur "Dell", incrémente le stock de 5. Affiche l'objet après chaque modification.

**Exercice 5.3** - Méthodes d'objets  
Crée un objet avec des méthodes : `calculatrice = {a: 5, b: 3, additionner() {return this.a + this.b}}`. Ajoute d'autres méthodes : soustraire, multiplier, diviser.

**Exercice 5.4** - Suppression de propriétés  
Crée `donnees = {a: 1, b: 2, c: 3, d: 4, e: 5}`. Supprime la propriété "c" avec `delete`, vérifie l'existence d'une propriété avec `"a" in donnees` ou `donnees.hasOwnProperty("a")`.

**Exercice 5.5** - Parcours d'objets  
Crée `notes = {Math: 15, Français: 14, Anglais: 16, Sciences: 13}`. Parcours avec `for...in` pour afficher chaque matière et note. Utilise aussi `Object.entries()` pour obtenir les paires clé-valeur.

**Exercice 5.6** - Object.assign et spread  
Crée `obj1 = {a: 1, b: 2}` et `obj2 = {b: 3, c: 4}`. Fusionne avec `Object.assign()` et avec spread `{...obj1, ...obj2}`. Crée une copie avec spread.

**Exercice 5.7** - Objets imbriqués  
Crée un objet d'étudiants :
```javascript
let etudiants = {
    alice: {age: 20, notes: [15, 16, 14]},
    bob: {age: 22, notes: [12, 13, 15]}
};
```
Accède à l'âge d'Alice, à la première note de Bob, modifie l'âge d'Alice, ajoute une note à Bob.

**Exercice 5.8** - Getters et setters  
Crée un objet avec getter et setter :
```javascript
let personne = {
    prenom: "John",
    nom: "Doe",
    get nomComplet() {return `${this.prenom} ${this.nom}`},
    set nomComplet(valeur) {/* parse et assigne */}
};
```

**Exercice 5.9** - Object.freeze et Object.seal  
Crée un objet. Utilise `Object.freeze()` pour le rendre complètement immutable. Crée un autre objet et utilise `Object.seal()` qui permet de modifier mais pas d'ajouter/supprimer des propriétés.

**Exercice 5.10** - Destructuring d'objets  
Crée `utilisateur = {nom: "Ali", age: 25, ville: "Paris", pays: "France"}`. Destructure : `let {nom, age} = utilisateur`. Utilise l'alias : `let {nom: nomUtilisateur} = utilisateur`. Utilise les valeurs par défaut.

---

### **Chapitre 6 — Conditions et structures de contrôle**

**Exercice 6.1** - If simple  
Demande l'âge de l'utilisateur avec `prompt()`. Si l'âge est >= 18, affiche "Vous êtes majeur", sinon affiche "Vous êtes mineur".

**Exercice 6.2** - If else if else  
Demande une note entre 0 et 20. Affiche la mention : "Excellent" (>= 16), "Bien" (>= 14), "Assez bien" (>= 12), "Passable" (>= 10), "Insuffisant" (< 10).

**Exercice 6.3** - Opérateurs logiques  
Demande le prix d'un produit et si l'utilisateur a une carte de fidélité. Si prix > 100 ET carte fidélité, réduction de 20%. Si prix > 100 OU carte fidélité, réduction de 10%. Utilise `&&` et `||`.

**Exercice 6.4** - Switch case  
Crée un programme qui demande un jour de la semaine (1-7) et affiche le nom du jour avec `switch`. Ajoute un `default` pour les valeurs invalides.

**Exercice 6.5** - Opérateur ternaire  
Réécris plusieurs conditions if/else en utilisant l'opérateur ternaire `condition ? valeurSiVrai : valeurSiFaux`. Exemple : `let statut = age >= 18 ? "majeur" : "mineur"`.

**Exercice 6.6** - Conditions imbriquées  
Crée un système de connexion : demande username et password. Vérifie d'abord si l'username existe, puis si le password est correct. Utilise des conditions imbriquées.

**Exercice 6.7** - Nullish coalescing  
Utilise l'opérateur `??` pour gérer les valeurs nullish (null ou undefined). Compare avec `||`. Exemple : `let nom = utilisateur.nom ?? "Anonyme"`.

**Exercice 6.8** - Optional chaining  
Utilise `?.` pour accéder en sécurité à des propriétés qui peuvent ne pas exister. Exemple : `utilisateur?.adresse?.ville`. Compare avec les vérifications traditionnelles.

**Exercice 6.9** - Short-circuit evaluation  
Utilise `&&` et `||` pour l'évaluation en court-circuit. Exemple : `estConnecte && afficherDashboard()`. Teste plusieurs cas d'usage.

**Exercice 6.10** - Validation complexe  
Crée un formulaire de validation : âge (entre 18 et 100), email (contient @), password (min 8 caractères). Affiche des messages d'erreur spécifiques pour chaque champ invalide.

---

### **Chapitre 7 — Boucles et itérations**

**Exercice 7.1** - Boucle for classique  
Affiche les nombres de 1 à 10 avec une boucle `for`. Puis affiche les nombres pairs de 0 à 20. Affiche les nombres de 10 à 1 en ordre décroissant.

**Exercice 7.2** - Boucle while  
Crée un compteur initialisé à 0. Avec une boucle `while`, incrémente-le et affiche-le jusqu'à ce qu'il atteigne 10. Crée aussi un programme qui demande "stop" pour arrêter.

**Exercice 7.3** - Boucle do...while  
Utilise `do...while` pour garantir qu'une action s'exécute au moins une fois. Crée un menu qui affiche des options et demande un choix jusqu'à ce que l'utilisateur choisisse "quitter".

**Exercice 7.4** - For...of sur tableaux  
Crée `fruits = ["pomme", "banane", "orange", "kiwi"]`. Parcours avec `for...of` et affiche chaque fruit. Compare avec la boucle `for` classique.

**Exercice 7.5** - For...in sur objets  
Crée `scores = {Alice: 95, Bob: 87, Charlie: 92}`. Parcours avec `for...in` et affiche chaque nom avec son score. Trouve et affiche le nom avec le meilleur score.

**Exercice 7.6** - Break et continue  
Affiche les nombres de 1 à 20, mais saute (continue) les multiples de 3 et arrête (break) à 15. Crée aussi une boucle qui cherche un élément dans un tableau et s'arrête quand elle le trouve.

**Exercice 7.7** - Boucles imbriquées  
Crée un programme avec deux boucles `for` imbriquées qui affiche une table de multiplication (de 1 à 10). Format : "3 x 4 = 12".

**Exercice 7.8** - ForEach  
Crée un tableau de nombres. Utilise `.forEach()` pour parcourir et afficher chaque élément avec son index. Compare avec `for...of` et boucle `for` classique.

**Exercice 7.9** - Boucle infinie contrôlée  
Crée une boucle `while(true)` avec une condition `break` à l'intérieur. Simule un jeu où l'utilisateur doit deviner un nombre et peut arrêter quand il veut.

**Exercice 7.10** - Performance des boucles  
Compare la performance de différentes boucles (for, while, forEach, for...of) en les chronométrant avec `console.time()` et `console.timeEnd()` sur un grand tableau.

---

## [IDEE] PARTIE 2 — Fonctions et programmation avancée

---

### **Chapitre 8 — Fonctions de base**

**Exercice 8.1** - Fonction simple  
Crée une fonction `direBonjour()` qui affiche "Bonjour !". Appelle-la 3 fois. Crée une fonction `direBonjourNom(nom)` qui affiche "Bonjour [nom] !".

**Exercice 8.2** - Fonctions avec return  
Crée des fonctions : `addition(a, b)`, `multiplication(a, b)`, `soustraction(a, b)`, `division(a, b)`. Chacune retourne le résultat. Teste toutes ces fonctions.

**Exercice 8.3** - Paramètres par défaut  
Crée une fonction `presenter(nom, age = 18, ville = "Paris")` avec des valeurs par défaut. Appelle-la de différentes façons : sans arguments optionnels, avec juste age, avec age et ville.

**Exercice 8.4** - Return multiple  
En JavaScript, on ne peut retourner qu'une valeur, mais on peut retourner un objet ou un tableau. Crée `calculerRectangle(longueur, largeur)` qui retourne `{perimetre: ..., aire: ...}`.

**Exercice 8.5** - Rest parameters  
Crée une fonction `somme(...nombres)` qui accepte un nombre variable d'arguments et retourne leur somme. Teste avec différents nombres d'arguments.

**Exercice 8.6** - Fonctions comme valeurs  
Assigne une fonction à une variable : `let multiplier = function(a, b) {return a * b}`. Passe une fonction comme argument à une autre fonction (callback simple).

**Exercice 8.7** - Portée (scope)  
Crée une variable globale et une variable locale. Explique la différence. Teste l'accès à une variable locale depuis l'extérieur (erreur). Crée un exemple de closure.

**Exercice 8.8** - Hoisting  
Teste le hoisting des fonctions : appelle une fonction AVANT sa déclaration (fonctionne avec `function`, pas avec `const/let`). Explique pourquoi.

**Exercice 8.9** - Fonction récursive  
Crée une fonction récursive `factorielle(n)` qui calcule n!. Par exemple : 5! = 5 × 4 × 3 × 2 × 1 = 120. Ajoute une condition de sortie pour éviter l'infini.

**Exercice 8.10** - IIFE (Immediately Invoked Function Expression)  
Crée une IIFE qui s'exécute immédiatement : `(function() { /* code */ })()`. Explique l'utilité (isolation de scope, pas de pollution globale).

---

### **Chapitre 9 — Arrow functions et fonctions avancées**

**Exercice 9.1** - Arrow function basique  
Convertis des fonctions classiques en arrow functions. Exemple : `function carre(x) {return x * x}` devient `const carre = (x) => x * x`. Teste différentes syntaxes.

**Exercice 9.2** - Arrow function avec un paramètre  
Quand il n'y a qu'un paramètre, les parenthèses sont optionnelles : `x => x * 2`. Quand il n'y a qu'une expression, le return est implicite. Crée plusieurs exemples.

**Exercice 9.3** - Arrow function et this  
Compare le comportement de `this` dans une fonction classique vs arrow function. Crée un objet avec une méthode utilisant `setTimeout` et montre la différence.

**Exercice 9.4** - Callbacks avec arrow functions  
Utilise des arrow functions comme callbacks dans `setTimeout`, `setInterval`, et les méthodes de tableaux. Exemple : `nombres.map(n => n * 2)`.

**Exercice 9.5** - Méthode bind  
Utilise `.bind()` pour lier une fonction à un contexte spécifique. Crée un exemple où tu fixes les valeurs de `this` et de certains arguments.

**Exercice 9.6** - Call et apply  
Utilise `.call()` et `.apply()` pour appeler une fonction avec un contexte spécifique. Comprends la différence entre les deux (passage d'arguments).

**Exercice 9.7** - Currying  
Crée une fonction curryfiée : `const multiplier = (a) => (b) => a * b`. Utilise-la : `const doubler = multiplier(2); doubler(5)`. Explique le concept.

**Exercice 9.8** - Composition de fonctions  
Crée des fonctions qui peuvent être composées. Exemple : `const compose = (f, g) => (x) => f(g(x))`. Utilise pour combiner plusieurs transformations.

**Exercice 9.9** - Memoization  
Implémente une fonction de memoization qui cache les résultats des appels de fonction. Teste avec une fonction coûteuse (calcul Fibonacci).

**Exercice 9.10** - Fonction générique  
Crée des fonctions génériques réutilisables : une fonction pour filtrer, une pour mapper, une pour réduire. Utilise-les sur différents types de données.

---

### **Chapitre 10 — Méthodes de tableaux avancées**

**Exercice 10.1** - Map  
Crée un tableau de nombres. Utilise `.map()` pour doubler chaque nombre. Crée aussi un tableau d'objets utilisateurs et utilise `.map()` pour extraire seulement les noms.

**Exercice 10.2** - Filter  
Crée un tableau de nombres. Utilise `.filter()` pour garder seulement les nombres pairs, puis les nombres > 10. Filtre un tableau d'objets selon une propriété.

**Exercice 10.3** - Reduce  
Utilise `.reduce()` pour : calculer la somme d'un tableau, trouver le max, compter les occurrences d'éléments, aplatir un tableau de tableaux.

**Exercice 10.4** - Find et findIndex  
Crée un tableau d'objets. Utilise `.find()` pour trouver le premier élément qui correspond à une condition. Utilise `.findIndex()` pour obtenir son index.

**Exercice 10.5** - Some et every  
Utilise `.some()` pour vérifier si AU MOINS UN élément satisfait une condition. Utilise `.every()` pour vérifier si TOUS les éléments satisfont une condition.

**Exercice 10.6** - Sort avec comparateur  
Trie un tableau de nombres (attention, sort est alphabétique par défaut). Utilise un comparateur : `nombres.sort((a, b) => a - b)`. Trie un tableau d'objets par une propriété.

**Exercice 10.7** - Chaînage de méthodes  
Chaîne plusieurs méthodes : filtre les nombres pairs, double-les, trie-les, somme-les. Exemple : `nombres.filter().map().sort().reduce()`.

**Exercice 10.8** - FlatMap  
Utilise `.flatMap()` pour mapper et aplatir en une seule opération. Compare avec `.map().flat()`. Crée un exemple d'extraction de mots depuis plusieurs phrases.

**Exercice 10.9** - From et entries  
Utilise `Array.from()` pour créer des tableaux depuis des strings, des sets, des maps. Utilise `.entries()` pour obtenir des paires [index, valeur].

**Exercice 10.10** - Traitement de données complexe  
Crée un tableau de transactions (achats avec date, montant, catégorie). Utilise les méthodes de tableaux pour : filtrer par catégorie, calculer total par catégorie, trouver la transaction la plus chère, grouper par mois.

---

### **Chapitre 11 — Programmation asynchrone : Callbacks et Promises**

**Exercice 11.1** - setTimeout et setInterval  
Utilise `setTimeout` pour exécuter du code après 2 secondes. Utilise `setInterval` pour exécuter du code toutes les secondes. Utilise `clearInterval` pour l'arrêter.

**Exercice 11.2** - Callbacks simples  
Crée une fonction qui prend un callback en paramètre et l'exécute après une action. Simule un téléchargement avec `setTimeout` et callback.

**Exercice 11.3** - Callback hell  
Crée une chaîne de callbacks imbriqués (callback hell). Exemple : télécharge un fichier, puis traite-le, puis sauvegarde, puis notifie. Observe la pyramide de doom.

**Exercice 11.4** - Première Promise  
Crée ta première Promise : `new Promise((resolve, reject) => {...})`. Résous-la après 1 seconde. Utilise `.then()` pour gérer le résultat.

**Exercice 11.5** - Promise avec reject  
Crée une Promise qui peut échouer (reject). Utilise `.catch()` pour gérer l'erreur. Utilise `.finally()` pour du code qui s'exécute toujours.

**Exercice 11.6** - Chaînage de Promises  
Chaîne plusieurs Promises avec `.then()`. Chaque étape transforme le résultat et le passe à la suivante. Refais le callback hell de l'exercice 11.3 avec des Promises.

**Exercice 11.7** - Promise.all  
Utilise `Promise.all()` pour attendre que plusieurs Promises se terminent. Exemple : télécharge 3 fichiers en parallèle, puis traite quand tous sont prêts.

**Exercice 11.8** - Promise.race  
Utilise `Promise.race()` qui résout dès que la première Promise se termine. Simule plusieurs serveurs et prends la réponse du plus rapide.

**Exercice 11.9** - Promise.allSettled  
Utilise `Promise.allSettled()` qui attend toutes les Promises, même celles qui échouent. Compare avec `Promise.all()` qui échoue si une seule échoue.

**Exercice 11.10** - Création d'API avec Promises  
Crée une petite bibliothèque d'API : `fetchUser(id)`, `fetchPosts(userId)`, `fetchComments(postId)`. Chaque fonction retourne une Promise. Chaîne-les pour obtenir toutes les données d'un utilisateur.

---

### **Chapitre 12 — Async/Await**

**Exercice 12.1** - Premier async/await  
Crée une fonction `async` qui utilise `await` sur une Promise. Compare la lisibilité avec `.then()`. Exemple : `async function getData() { const data = await fetch(...) }`.

**Exercice 12.2** - Try/catch avec async  
Utilise `try/catch` pour gérer les erreurs dans une fonction async. Compare avec `.catch()` des Promises. Gère plusieurs niveaux d'erreurs possibles.

**Exercice 12.3** - Async/await avec Promise.all  
Utilise `await Promise.all()` pour attendre plusieurs Promises en parallèle dans une fonction async. Plus lisible que le chaînage de .then().

**Exercice 12.4** - Sequential vs parallel  
Compare l'exécution séquentielle (`await` l'un après l'autre) vs parallèle (`Promise.all`). Mesure la différence de temps avec 3 opérations de 1 seconde chacune.

**Exercice 12.5** - Top-level await  
Dans un module ES, teste le top-level await (await en dehors d'une fonction async). Attention, cela bloque le chargement du module.

**Exercice 12.6** - Gestion d'erreurs robuste  
Crée une fonction async avec plusieurs niveaux de try/catch. Gère différents types d'erreurs différemment. Utilise `finally` pour le nettoyage.

**Exercice 12.7** - Timeout avec async  
Crée une fonction qui ajoute un timeout à n'importe quelle Promise. Utilise `Promise.race` entre la Promise et un timeout. Rejette si le timeout est dépassé.

**Exercice 12.8** - Retry mechanism  
Implémente une fonction qui réessaie une opération async en cas d'échec. Paramètres : nombre max de tentatives, délai entre tentatives. Utilise une boucle avec await.

**Exercice 12.9** - Async iterators  
Crée un async iterator avec `Symbol.asyncIterator`. Utilise `for await...of` pour le parcourir. Simule un flux de données qui arrive progressivement.

**Exercice 12.10** - API client complet  
Crée un client API complet avec async/await : fonction pour GET, POST, PUT, DELETE. Gestion d'erreurs, retry automatique, timeout, intercepteurs. Utilise fetch() ou simule.

---

## [WEB] PARTIE 3 — JavaScript pour le Web (DOM et événements)

---

### **Chapitre 13 — DOM : Sélection et manipulation**

**Exercice 13.1** - Sélection d'éléments  
Utilise `document.getElementById()`, `.getElementsByClassName()`, `.getElementsByTagName()`, `.querySelector()`, `.querySelectorAll()`. Compare les différences et performances.

**Exercice 13.2** - Modification de contenu  
Sélectionne des éléments et modifie leur contenu avec `.innerHTML`, `.textContent`, `.innerText`. Comprends les différences et quand utiliser chaque méthode.

**Exercice 13.3** - Modification d'attributs  
Utilise `.getAttribute()`, `.setAttribute()`, `.removeAttribute()`, `.hasAttribute()`. Modifie des attributs comme `src`, `href`, `alt`, `data-*`.

**Exercice 13.4** - Manipulation de classes  
Utilise `.classList.add()`, `.remove()`, `.toggle()`, `.contains()`, `.replace()`. Crée un bouton qui toggle une classe "active" sur un élément.

**Exercice 13.5** - Styles inline  
Modifie les styles avec `.style.property`. Change couleur, taille, position, etc. Attention : les noms de propriétés sont en camelCase (`backgroundColor`).

**Exercice 13.6** - Création d'éléments  
Utilise `document.createElement()`, `.createTextNode()`, `.appendChild()`, `.append()`. Crée dynamiquement une liste d'éléments depuis un tableau.

**Exercice 13.7** - Insertion et suppression  
Utilise `.insertBefore()`, `.insertAdjacentHTML()`, `.remove()`, `.removeChild()`. Crée un gestionnaire de tâches qui permet d'ajouter et supprimer des items.

**Exercice 13.8** - Clonage d'éléments  
Utilise `.cloneNode(true)` pour cloner un élément avec tous ses enfants. Crée un bouton "Dupliquer" qui clone un élément du DOM.

**Exercice 13.9** - Navigation dans le DOM  
Utilise `.parentElement`, `.children`, `.firstElementChild`, `.lastElementChild`, `.nextElementSibling`, `.previousElementSibling`. Crée une fonction qui parcourt l'arbre du DOM.

**Exercice 13.10** - Formulaire dynamique  
Crée un formulaire dynamique : ajoute des champs de saisie avec un bouton "+", supprime avec un bouton "-", valide avant soumission, affiche les données collectées.

---

### **Chapitre 14 — Événements**

**Exercice 14.1** - Event listeners basiques  
Utilise `.addEventListener()` sur différents événements : `click`, `mouseover`, `mouseout`, `keydown`, `keyup`. Compare avec les attributs HTML `onclick`.

**Exercice 14.2** - Event object  
Dans le handler d'événement, explore l'objet `event`. Accède à : `.target`, `.currentTarget`, `.type`, `.preventDefault()`, `.stopPropagation()`.

**Exercice 14.3** - Événements de souris  
Gère tous les événements de souris : `click`, `dblclick`, `mousedown`, `mouseup`, `mousemove`, `mouseenter`, `mouseleave`. Crée un dessinateur simple qui trace au mouvement de la souris.

**Exercice 14.4** - Événements de clavier  
Gère `keydown`, `keyup`, `keypress`. Récupère `.key`, `.code`, `.keyCode`. Crée un jeu simple contrôlé au clavier (déplace un élément avec les flèches).

**Exercice 14.5** - Événements de formulaire  
Gère `submit`, `focus`, `blur`, `change`, `input`. Crée une validation de formulaire en temps réel : vérifie chaque champ quand l'utilisateur tape ou quitte le champ.

**Exercice 14.6** - Event delegation  
Au lieu d'attacher un listener à chaque élément d'une liste, attache-le au parent. Utilise `event.target` pour savoir quel enfant a été cliqué. Plus performant pour les grandes listes.

**Exercice 14.7** - Prevent default  
Utilise `.preventDefault()` pour empêcher le comportement par défaut : empêche la soumission d'un formulaire, empêche un lien de naviguer, empêche le menu contextuel (clic droit).

**Exercice 14.8** - Stop propagation  
Comprends la propagation d'événements (bubbling). Utilise `.stopPropagation()` pour l'arrêter. Crée des éléments imbriqués avec des listeners et teste le bubbling.

**Exercice 14.9** - Custom events  
Crée et dispatch des événements personnalisés avec `new CustomEvent()` et `.dispatchEvent()`. Crée un système de communication entre composants via des events.

**Exercice 14.10** - Debounce et throttle  
Implémente des fonctions de debounce et throttle pour limiter la fréquence d'exécution d'event handlers. Teste sur un événement `scroll` ou `resize`.

---

### **Chapitre 15 — Projets DOM interactifs**

**Exercice 15.1** - Todo List  
Crée une application de todo list complète : ajouter des tâches, marquer comme complété (toggle), supprimer, filtrer (toutes/actives/complétées), compter les tâches actives.

**Exercice 15.2** - Modal / Popup  
Crée une modal réutilisable : s'ouvre avec un bouton, se ferme avec X ou en cliquant à l'extérieur, peut contenir n'importe quel contenu HTML, gère l'événement escape.

**Exercice 15.3** - Tabs / Onglets  
Crée un système d'onglets : plusieurs panneaux de contenu, un seul visible à la fois, navigation par clic sur les onglets, indication visuelle de l'onglet actif.

**Exercice 15.4** - Accordion  
Crée un accordion : plusieurs sections, clic sur header toggle le contenu, peut autoriser plusieurs sections ouvertes ou une seule à la fois, animation de transition.

**Exercice 15.5** - Carousel / Slider  
Crée un carousel d'images : navigation précédent/suivant, indicateurs (dots), autoplay optionnel, pause au hover, navigation infinie (boucle).

**Exercice 15.6** - Drag and Drop  
Implémente le drag and drop : rends des éléments draggables, définis des zones de drop, change le style pendant le drag, réorganise des éléments par drag.

**Exercice 15.7** - Filtres et recherche  
Crée une liste d'items avec filtres : recherche textuelle, filtres par catégorie, tri (alphabétique, prix), combinaison de filtres, update en temps réel.

**Exercice 15.8** - Quiz interactif  
Crée un quiz : affiche les questions une par une, sélection de réponse, validation, score final, feedback immédiat, possibilité de recommencer.

**Exercice 15.9** - Calculatrice  
Crée une calculatrice fonctionnelle : boutons pour chiffres et opérations, affichage du résultat, gestion des décimales, clear, delete, opérations chaînées.

**Exercice 15.10** - Form validator  
Crée un système de validation complet : validation en temps réel, messages d'erreur, styles de champs invalides, validation avant soumission, patterns regex, confirmation password.

---

## [BRICK] PARTIE 4 — Programmation orientée objet (POO)

---

### **Chapitre 16 — Classes et objets**

**Exercice 16.1** - Première classe  
Crée une classe `Personne` avec un `constructor(nom, age)`. Ajoute une méthode `sePresenter()` qui affiche "Je m'appelle [nom] et j'ai [age] ans". Crée 3 instances.

**Exercice 16.2** - Propriétés et méthodes  
Crée une classe `Voiture` avec propriétés : `marque`, `modele`, `annee`, `kilometrage`. Ajoute des méthodes : `rouler(km)` qui augmente le kilométrage, `afficherInfo()`.

**Exercice 16.3** - Getters et setters  
Crée une classe avec des getters et setters. Exemple : `get nomComplet()` et `set nomComplet(valeur)`. Valide les données dans le setter (âge positif, email valide, etc.).

**Exercice 16.4** - Propriétés privées  
Utilise la syntaxe `#` pour créer des propriétés privées : `#solde`. Ces propriétés ne sont accessibles que depuis l'intérieur de la classe. Crée des méthodes publiques pour y accéder.

**Exercice 16.5** - Méthodes statiques  
Crée des méthodes statiques avec `static`. Ces méthodes appartiennent à la classe, pas aux instances. Exemple : `Math.random()` est statique. Crée `Utilitaire.formaterDate()`.

**Exercice 16.6** - Propriétés statiques  
Crée des propriétés statiques. Exemple : compteur d'instances. Chaque fois qu'un objet est créé, incrémente `Classe.compteur`. Accessible via la classe, pas l'instance.

**Exercice 16.7** - This et contexte  
Comprends le contexte de `this` dans les méthodes. Teste avec des callbacks et arrow functions. Utilise `.bind()` pour fixer le contexte si nécessaire.

**Exercice 16.8** - Interaction entre objets  
Crée deux classes : `Etudiant` (nom, notes) et `Classe` (nom, liste étudiants). Dans Classe, ajoute méthodes : `ajouterEtudiant()`, `moyenneClasse()`, `meilleurEtudiant()`.

**Exercice 16.9** - Instanceof  
Utilise `instanceof` pour vérifier si un objet est une instance d'une classe. Crée une fonction qui traite différemment selon le type d'objet.

**Exercice 16.10** - Classe complète  
Crée une classe `CompteBancaire` : propriétés privées (solde), méthodes (deposer, retirer, consulterSolde), validations (solde >= 0), historique des transactions, toString().

---

### **Chapitre 17 — Héritage et polymorphisme**

**Exercice 17.1** - Héritage simple  
Crée une classe parente `Animal` avec `constructor(nom, age)` et méthode `parler()`. Crée des classes enfants `Chien` et `Chat` qui `extends Animal` et redéfinissent `parler()`.

**Exercice 17.2** - Super  
Dans une classe enfant, utilise `super()` dans le constructor pour appeler le constructor parent. Utilise `super.methode()` pour appeler une méthode du parent.

**Exercice 17.3** - Override de méthodes  
Redéfinis complètement une méthode du parent dans l'enfant. Crée une méthode `calculerSalaire()` différente pour `EmployeHoraire` et `EmployeMensuel`.

**Exercice 17.4** - Héritage multi-niveaux  
Crée une hiérarchie : `EtreVivant` -> `Animal` -> `Mammifere` -> `Chien`. Chaque niveau ajoute des propriétés/méthodes. Vérifie l'héritage complet.

**Exercice 17.5** - Instanceof avec héritage  
Teste `instanceof` sur une hiérarchie de classes. Un `Chien` est instanceof `Chien`, `Animal`, `EtreVivant`, et `Object`.

**Exercice 17.6** - Polymorphisme  
Crée une classe `Forme` avec méthode `aire()`. Crée `Rectangle`, `Cercle`, `Triangle` qui héritent et implémentent `aire()` différemment. Crée un tableau de formes mixtes et calcule l'aire totale.

**Exercice 17.7** - Protected (simulation)  
JavaScript n'a pas de `protected`, mais tu peux le simuler avec des conventions (préfixe `_`) et des getters/setters contrôlés. Crée un exemple.

**Exercice 17.8** - Composition vs héritage  
Compare héritage et composition. Crée `Voiture` qui contient un objet `Moteur` (composition) plutôt que d'hériter. Discute quand utiliser l'un ou l'autre.

**Exercice 17.9** - Mixin pattern  
JavaScript ne supporte pas l'héritage multiple, mais tu peux utiliser des mixins. Crée des mixins pour ajouter des fonctionnalités à plusieurs classes différentes.

**Exercice 17.10** - Système avec héritage  
Crée un système de gestion de bibliothèque : classe parente `Document` (titre, auteur, annee), classes enfants `Livre` (pages, isbn), `Magazine` (numero, mois), `DVD` (duree). Méthode `afficherInfo()` polymorphe.

---

### **Chapitre 18 — Design patterns en JavaScript**

**Exercice 18.1** - Singleton  
Implémente le pattern Singleton : une classe qui ne peut avoir qu'une seule instance. En JavaScript, tu peux utiliser une variable privée ou un module.

**Exercice 18.2** - Factory  
Crée une Factory qui crée différents types d'objets selon un paramètre. Exemple : `VehiculeFactory.creer('voiture')` retourne une Voiture, `.creer('moto')` retourne une Moto.

**Exercice 18.3** - Observer  
Implémente le pattern Observer : un sujet maintient une liste d'observateurs et les notifie automatiquement de tout changement d'état. Utile pour les événements personnalisés.

**Exercice 18.4** - Module pattern  
Utilise le module pattern pour encapsuler du code : variables/fonctions privées, interface publique. Avec IIFE ou modules ES6.

**Exercice 18.5** - Decorator pattern  
Ajoute dynamiquement des fonctionnalités à un objet. Différent du décorateur Python, c'est une enveloppe autour d'un objet existant qui ajoute du comportement.

**Exercice 18.6** - Strategy pattern  
Définis une famille d'algorithmes interchangeables. Exemple : différentes stratégies de tri ou de validation. Le client peut changer de stratégie à la volée.

**Exercice 18.7** - Builder pattern  
Construis des objets complexes étape par étape. Exemple : `new PizzaBuilder().ajouterFromage().ajouterJambon().construire()`. Facilite la création d'objets avec beaucoup d'options.

**Exercice 18.8** - Proxy pattern  
Crée un proxy qui contrôle l'accès à un objet. En ES6, utilise l'objet `Proxy` pour intercepter les opérations sur un objet (get, set, etc.).

**Exercice 18.9** - Command pattern  
Encapsule une requête comme un objet. Permet de paramétrer des opérations, de les mettre en file d'attente, et de les annuler (undo/redo).

**Exercice 18.10** - Facade pattern  
Fournis une interface simplifiée à un système complexe. Masque la complexité derrière une API simple. Exemple : une classe `API` qui simplifie plusieurs appels fetch complexes.

---

## [CONFIG] PARTIE 5 — JavaScript moderne et outillage

---

### **Chapitre 19 — Modules ES6**

**Exercice 19.1** - Export/Import nommés  
Crée un module avec plusieurs exports nommés : `export const PI = 3.14; export function ajouter(a, b) {...}`. Importe-les avec `import { PI, ajouter } from './module.js'`.

**Exercice 19.2** - Export default  
Crée un module avec un export par défaut : `export default class Calculatrice {...}`. Importe avec `import Calculatrice from './calculatrice.js'`.

**Exercice 19.3** - Alias d'import  
Importe avec des alias pour éviter les conflits de noms : `import { addition as add, multiplication as mult } from './math.js'`.

**Exercice 19.4** - Import de tout  
Importe tout un module : `import * as MathUtils from './math.js'`. Accède aux exports via `MathUtils.fonction()`.

**Exercice 19.5** - Re-export  
Crée un module "barrel" qui re-exporte d'autres modules : `export { Classe1 } from './module1.js'; export { Classe2 } from './module2.js'`. Point d'entrée unique.

**Exercice 19.6** - Import dynamique  
Utilise `import()` pour charger un module dynamiquement (retourne une Promise). Utile pour le code splitting : `const module = await import('./gros-module.js')`.

**Exercice 19.7** - Module vs script  
Comprends les différences entre un script classique et un module : scope, strict mode, imports, this, defer par défaut. Teste les deux.

**Exercice 19.8** - Structure de projet modulaire  
Organise un projet en modules : un fichier par classe/fonctionnalité, un index.js qui exporte tout, imports relatifs vs absolus. Crée une structure propre.

**Exercice 19.9** - Tree shaking  
Comprends le concept de tree shaking (élimination du code mort). Avec un bundler, seuls les exports utilisés sont inclus. Teste avec un outil comme Vite.

**Exercice 19.10** - CommonJS vs ES Modules  
Compare les deux systèmes : `require/module.exports` (CommonJS, Node.js) vs `import/export` (ES Modules). Comprends quand utiliser chaque système.

---

### **Chapitre 20 — Destructuring et spread/rest**

**Exercice 20.1** - Destructuring de tableaux  
Destructure des tableaux : `let [a, b, c] = [1, 2, 3]`. Saute des éléments : `let [premier, , troisieme] = tableau`. Valeurs par défaut : `let [a = 0] = []`.

**Exercice 20.2** - Destructuring d'objets  
Destructure des objets : `let {nom, age} = personne`. Alias : `let {nom: userName} = personne`. Valeurs par défaut : `let {age = 18} = {}`.

**Exercice 20.3** - Destructuring imbriqué  
Destructure des structures imbriquées : `let {adresse: {ville, pays}} = utilisateur`. Combine tableaux et objets : `let [{nom}] = tableauObjets`.

**Exercice 20.4** - Destructuring dans les paramètres  
Utilise le destructuring directement dans les paramètres de fonction : `function afficher({nom, age}) {...}`. Simplifie l'accès aux propriétés.

**Exercice 20.5** - Rest operator dans destructuring  
Utilise `...` pour capturer le reste : `let [premier, ...reste] = tableau` ou `let {nom, ...autres} = objet`. Utile pour séparer certaines propriétés.

**Exercice 20.6** - Spread operator sur tableaux  
Utilise `...` pour étendre un tableau : `[...tab1, ...tab2]` pour concaténer, `[...tableau]` pour copier, `[0, ...tableau, 100]` pour insérer.

**Exercice 20.7** - Spread operator sur objets  
Utilise `...` pour étendre/fusionner des objets : `{...obj1, ...obj2}`. Les propriétés de obj2 écrasent celles de obj1 en cas de conflit.

**Exercice 20.8** - Copie shallow vs deep  
Comprends que spread fait une copie shallow (surface). Les objets imbriqués restent liés. Teste avec des objets imbriqués. Pour deep copy, utilise structuredClone() ou autres méthodes.

**Exercice 20.9** - Rest parameters  
Utilise rest parameters dans les fonctions : `function somme(...nombres) {...}`. Capture tous les arguments dans un tableau. Compare avec `arguments`.

**Exercice 20.10** - Combinaisons avancées  
Combine destructuring, spread et rest dans des cas complexes : swap de variables, merge d'objets avec override, extraction + copie du reste, etc.

---

### **Chapitre 21 — Template literals et tagged templates**

**Exercice 21.1** - Template literals basiques  
Utilise les backticks pour créer des chaînes multi-lignes, interpoler des variables : \`Hello ${nom}\`, expressions : \`Prix TTC: ${prix * 1.2}\`.

**Exercice 21.2** - Multi-lignes  
Crée des chaînes sur plusieurs lignes sans caractère d'échappement. Utile pour du HTML, des templates, des requêtes SQL, etc.

**Exercice 21.3** - Expressions complexes  
Mets des expressions complexes dans \${} : appels de fonction, opérateurs ternaires, accès à des propriétés, etc. Teste les limites.

**Exercice 21.4** - Échappement dans templates  
Comprends comment échapper les backticks et \${}. Utilise `\`` et `\${` quand tu veux les afficher littéralement.

**Exercice 21.5** - Tagged templates intro  
Crée une fonction tag qui transforme un template : `function tag(strings, ...values) {...}`. Utilise : `tag\`Hello ${nom}\``. La fonction reçoit les parties fixes et les valeurs.

**Exercice 21.6** - HTML sanitizer  
Crée un tag template qui échappe le HTML pour éviter les XSS : `html\`<div>${userInput}</div>\`` doit échapper les caractères dangereux de userInput.

**Exercice 21.7** - Style tag  
Crée un tag template pour générer du CSS : `css\`color: ${color};\`` qui gère les unités automatiquement, valide les couleurs, etc.

**Exercice 21.8** - Internationalization tag  
Crée un tag pour la traduction : `t\`Hello ${nom}\`` qui cherche la traduction de "Hello" dans la langue actuelle et interpole les variables.

**Exercice 21.9** - SQL query builder  
Crée un tag template pour construire des requêtes SQL sécurisées : échappe automatiquement les valeurs pour éviter l'injection SQL.

**Exercice 21.10** - Custom formatter  
Crée un tag qui formate automatiquement : nombres (avec séparateurs), dates (locale), currency (symbole), etc. Détecte le type et formate en conséquence.

---

### **Chapitre 22 — Symboles et itérateurs**

**Exercice 22.1** - Création de symboles  
Crée des symboles avec `Symbol()` et `Symbol.for()`. Comprends que chaque symbole est unique. Utilise-les comme clés de propriétés uniques.

**Exercice 22.2** - Well-known symbols  
Explore les symboles built-in : `Symbol.iterator`, `Symbol.toStringTag`, `Symbol.hasInstance`, etc. Comprends leur utilité.

**Exercice 22.3** - Symbol comme clé  
Utilise des symboles comme clés de propriétés pour créer des propriétés "cachées". Elles n'apparaissent pas dans `Object.keys()` ou `for...in`.

**Exercice 22.4** - Premier itérateur  
Crée un objet itérable manuellement : implémente `[Symbol.iterator]()` qui retourne un objet avec `next()`. Rends un objet utilisable dans `for...of`.

**Exercice 22.5** - Générateur basique  
Utilise une fonction génératrice `function* gen() { yield 1; yield 2; }` pour créer un itérateur plus facilement. Comprends `yield` et `next()`.

**Exercice 22.6** - Générateur infini  
Crée un générateur infini : `function* nombres() { let n = 0; while(true) yield n++; }`. Utilise-le avec prudence (limite les itérations).

**Exercice 22.7** - Yield*  
Utilise `yield*` pour déléguer à un autre itérable : `function* gen() { yield* [1,2,3]; yield* autreGen(); }`. Compose des générateurs.

**Exercice 22.8** - Générateur avec paramètres  
Envoie des valeurs dans un générateur avec `.next(value)`. La valeur est reçue par l'expression `yield`. Crée une conversation bidirectionnelle.

**Exercice 22.9** - Iterator protocol  
Implémente manuellement le protocol d'itération : objet avec `next()` qui retourne `{value, done}`. Compare avec les générateurs (plus simple).

**Exercice 22.10** - Itérables custom  
Crée une classe itérable personnalisée : `Range(start, end)` qui itère de start à end, `Tree` qui parcourt un arbre, `Fibonacci` qui génère la suite.

---

### **Chapitre 23 — Map, Set, WeakMap, WeakSet**

**Exercice 23.1** - Map basique  
Crée un `Map`. Ajoute des paires clé-valeur avec `.set()`, récupère avec `.get()`, vérifie avec `.has()`, supprime avec `.delete()`. Compare avec les objets.

**Exercice 23.2** - Map avec clés de tout type  
Dans un Map, les clés peuvent être de n'importe quel type (objets, fonctions, etc.), contrairement aux objets (seulement strings/symbols). Démontre cette différence.

**Exercice 23.3** - Parcours de Map  
Parcours un Map avec `for...of` (itère sur [clé, valeur]), `.forEach()`, `.keys()`, `.values()`, `.entries()`. Compare les différentes méthodes.

**Exercice 23.4** - Set basique  
Crée un `Set` pour stocker des valeurs uniques. Ajoute avec `.add()`, vérifie avec `.has()`, supprime avec `.delete()`. Élimine automatiquement les doublons.

**Exercice 23.5** - Opérations sur Sets  
Implémente union, intersection, différence entre deux Sets. JavaScript n'a pas ces méthodes natives, crée-les avec spread et filter.

**Exercice 23.6** - Conversion Set <-> Array  
Convertis un tableau en Set pour éliminer les doublons : `[...new Set(tableau)]`. Convertis un Set en tableau pour utiliser les méthodes de tableaux.

**Exercice 23.7** - WeakMap  
Crée un `WeakMap`. Les clés doivent être des objets. Les entrées sont garbage collectées quand les clés n'ont plus de références. Pas énumérable (pas de `.keys()`, `.size`, etc.).

**Exercice 23.8** - WeakSet  
Crée un `WeakSet` pour stocker des objets faiblement référencés. Utile pour marquer des objets sans empêcher leur garbage collection.

**Exercice 23.9** - Use cases WeakMap  
Utilise WeakMap pour stocker des données privées associées à un objet, ou pour un cache où les entrées sont automatiquement nettoyées.

**Exercice 23.10** - Performance comparisons  
Compare les performances de Map vs Object, Set vs Array pour différentes opérations (ajout, recherche, suppression). Choisis la bonne structure selon le cas.

---

### **Chapitre 24 — Proxy et Reflect**

**Exercice 24.1** - Premier Proxy  
Crée un Proxy de base : `new Proxy(target, handler)`. Intercept l'accès aux propriétés avec le trap `get`. Affiche un message à chaque accès.

**Exercice 24.2** - Validation avec set  
Utilise le trap `set` pour valider les valeurs avant de les assigner. Exemple : vérifie que l'âge est un nombre positif, que l'email contient @, etc.

**Exercice 24.3** - Valeurs par défaut  
Avec le trap `get`, retourne une valeur par défaut si la propriété n'existe pas au lieu de `undefined`. Crée un objet qui ne retourne jamais undefined.

**Exercice 24.4** - Propriétés privées avec Proxy  
Utilise un Proxy pour cacher les propriétés qui commencent par `_`. Dans `get` et `set`, refuse l'accès aux propriétés privées depuis l'extérieur.

**Exercice 24.5** - Logging automatique  
Crée un Proxy qui log automatiquement tous les accès et modifications : "Lecture de propriété 'nom'", "Modification de 'age' : 25 -> 26".

**Exercice 24.6** - Has trap  
Utilise le trap `has` pour personnaliser l'opérateur `in`. Exemple : cache certaines propriétés pour qu'elles n'apparaissent pas dans `'prop' in obj`.

**Exercice 24.7** - DeleteProperty trap  
Intercept la suppression de propriétés avec `deleteProperty`. Empêche la suppression de certaines propriétés importantes ou log les suppressions.

**Exercice 24.8** - Reflect API  
Utilise `Reflect` pour les opérations par défaut dans les traps. Exemple : `Reflect.get(target, prop)` au lieu de `target[prop]`. Plus cohérent et retourne des booléens.

**Exercice 24.9** - Proxy de fonction  
Crée un Proxy d'une fonction avec le trap `apply`. Intercept les appels de fonction : log les arguments, valide les paramètres, mesure le temps d'exécution.

**Exercice 24.10** - Proxy chaîné  
Crée des Proxies imbriqués : un Proxy d'un objet dont les propriétés sont elles-mêmes des Proxies. Utile pour des validations multi-niveaux.

---

## [RAPIDE] PARTIE 6 — JavaScript pour Node.js et Backend

---

### **Chapitre 25 — Introduction à Node.js**

**Exercice 25.1** - Premier script Node  
Crée un fichier `.js` avec `console.log("Hello Node!")`. Exécute avec `node fichier.js`. Comprends que tu n'es plus dans un navigateur.

**Exercice 25.2** - Process object  
Explore `process` : `.version`, `.platform`, `.argv` (arguments ligne de commande), `.env` (variables d'environnement), `.exit()`, `.cwd()`.

**Exercice 25.3** - Arguments de ligne de commande  
Crée un script qui accepte des arguments : `node script.js arg1 arg2`. Accède avec `process.argv` (les 2 premiers sont node et le script).

**Exercice 25.4** - Variables d'environnement  
Utilise `process.env` pour lire des variables d'environnement. Teste en définissant : `PORT=3000 node server.js`. Utilise dotenv pour charger depuis `.env`.

**Exercice 25.5** - Lecture de fichiers  
Utilise le module `fs` pour lire un fichier : `fs.readFileSync()` (synchrone) et `fs.readFile()` (asynchrone avec callback). Compare les deux.

**Exercice 25.6** - Écriture de fichiers  
Écris dans un fichier avec `fs.writeFile()`. Append avec `fs.appendFile()`. Crée un logger simple qui écrit dans un fichier de log.

**Exercice 25.7** - Opérations sur fichiers/dossiers  
Utilise `fs` pour : créer un dossier (`.mkdir()`), lister les fichiers (`.readdir()`), supprimer un fichier (`.unlink()`), renommer (`.rename()`).

**Exercice 25.8** - Module path  
Utilise le module `path` pour manipuler les chemins : `.join()`, `.resolve()`, `.basename()`, `.dirname()`, `.extname()`. Gère les différences OS.

**Exercice 25.9** - Module os  
Explore le module `os` : `.platform()`, `.cpus()`, `.totalmem()`, `.freemem()`, `.homedir()`, `.tmpdir()`. Affiche les infos système.

**Exercice 25.10** - Script utilitaire Node  
Crée un script CLI utile : renommeur de fichiers en masse, convertisseur de fichiers, générateur de fichiers depuis template, etc. Utilise les modules vus.

---

### **Chapitre 26 — HTTP et serveurs**

**Exercice 26.1** - Premier serveur HTTP  
Crée un serveur HTTP basique avec le module `http` : écoute sur un port, répond "Hello World" à toutes les requêtes. Lance avec `node server.js`.

**Exercice 26.2** - Routing basique  
Dans ton serveur, vérifie `req.url` pour router vers différentes pages : `/`, `/about`, `/contact`. Retourne du contenu différent pour chaque route.

**Exercice 26.3** - Méthodes HTTP  
Gère différentes méthodes HTTP : `req.method` pour différencier GET, POST, PUT, DELETE. Répond différemment selon la méthode.

**Exercice 26.4** - Query parameters  
Parse les query parameters d'une URL : `/search?q=javascript&sort=date`. Utilise le module `url` et `URLSearchParams`. Affiche les paramètres.

**Exercice 26.5** - Lecture du body POST  
Lis le body d'une requête POST. Les données arrivent par chunks : écoute `'data'` et `'end'` sur `req`. Concatène et parse le body.

**Exercice 26.6** - Servir des fichiers statiques  
Crée un serveur qui sert des fichiers statiques (HTML, CSS, JS, images). Lis le fichier demandé et retourne avec le bon Content-Type.

**Exercice 26.7** - Headers HTTP  
Manipule les headers : lis les headers de la requête (`req.headers`), définis les headers de la réponse (`res.setHeader()`). Gère Content-Type, Cache-Control, etc.

**Exercice 26.8** - Status codes  
Utilise les bons status codes HTTP : 200 (OK), 404 (Not Found), 500 (Server Error), 301 (Redirect), etc. Gère les erreurs proprement.

**Exercice 26.9** - Fetch depuis Node  
Fais des requêtes HTTP depuis Node (client). Utilise le module `https` natif ou installe `node-fetch`. Récupère des données d'une API.

**Exercice 26.10** - API REST simple  
Crée une API REST complète : endpoints GET, POST, PUT, DELETE pour une ressource. Stocke les données en mémoire (tableau). Teste avec un client HTTP (curl, Postman).

---

### **Chapitre 27 — Express.js**

**Exercice 27.1** - Setup Express  
Installe Express : `npm install express`. Crée ton premier serveur Express : plus simple que http natif. Route basique : `app.get('/', (req, res) => res.send('Hello'))`.

**Exercice 27.2** - Routes Express  
Crée plusieurs routes : `app.get()`, `app.post()`, `app.put()`, `app.delete()`. Paramètres de route : `app.get('/users/:id')` et accède avec `req.params.id`.

**Exercice 27.3** - Middleware  
Crée et utilise des middlewares : fonctions qui s'exécutent avant les routes. Logger, authentification, parsing body. Utilise `app.use()`. Comprends `next()`.

**Exercice 27.4** - Query et body  
Accède aux query parameters avec `req.query`. Parse le body JSON avec `express.json()` middleware. Accède avec `req.body`.

**Exercice 27.5** - Serving static  
Sers des fichiers statiques avec `express.static()`. Crée un dossier `public/` avec HTML/CSS/JS, rends-le accessible.

**Exercice 27.6** - Template engine  
Installe et configure un moteur de templates (EJS, Pug, Handlebars). Rends des pages dynamiques : `res.render('page', {data})`. Passe des variables aux templates.

**Exercice 27.7** - Error handling  
Gère les erreurs avec un middleware d'erreur : 4 paramètres `(err, req, res, next)`. Catch les erreurs dans les routes avec try/catch et passe à `next(err)`.

**Exercice 27.8** - Router modulaire  
Utilise `express.Router()` pour organiser les routes en modules. Crée `routes/users.js`, `routes/posts.js`, importe dans `app.js` avec `app.use('/users', userRouter)`.

**Exercice 27.9** - Validation et sanitization  
Utilise `express-validator` pour valider et nettoyer les données entrantes. Valide les paramètres, body, query. Retourne des erreurs claires.

**Exercice 27.10** - API REST complète  
Crée une API REST complète avec Express : CRUD pour plusieurs ressources, authentification JWT, validation, error handling, structure modulaire, documentation.

---

### **Chapitre 28 — Base de données avec Node.js**

**Exercice 28.1** - SQLite avec Node  
Installe `better-sqlite3`. Crée une DB, une table, insère des données, requête. Opérations synchrones, simple pour débuter.

**Exercice 28.2** - Requêtes préparées  
Utilise des requêtes préparées pour éviter l'injection SQL : `.prepare(sql).run(params)`. Ne concatène JAMAIS directement les valeurs utilisateur.

**Exercice 28.3** - Transactions  
Utilise des transactions pour garantir la cohérence : commence, exécute plusieurs opérations, commit si tout ok, rollback si erreur.

**Exercice 28.4** - MongoDB avec Mongoose  
Installe MongoDB et Mongoose. Définis un schema Mongoose, crée un model. CRUD avec Mongoose : `.create()`, `.find()`, `.findById()`, `.updateOne()`, `.deleteOne()`.

**Exercice 28.5** - Relations Mongoose  
Crée des relations entre documents : référence (ObjectId), population (`.populate()`). Exemple : User -> Posts (un-à-plusieurs).

**Exercice 28.6** - Validation Mongoose  
Définis des validations dans le schema : required, unique, min/max, enum, regex. Les validations s'exécutent avant save.

**Exercice 28.7** - Middleware Mongoose  
Utilise les middleware (hooks) : `pre('save')`, `post('save')`. Hash un password avant save, log après save, etc.

**Exercice 28.8** - Pagination  
Implémente la pagination : `.skip()` et `.limit()` avec Mongoose. Retourne aussi le total count, nombre de pages, page actuelle.

**Exercice 28.9** - Recherche et filtrage  
Implémente une recherche avec filtres multiples, tri, pagination. Query builder avec Mongoose. Exemple : API de recherche de produits.

**Exercice 28.10** - ORM comparison  
Compare les approches : SQL brut, query builder (Knex), ORM (Sequelize, Prisma, Mongoose). Avantages/inconvénients de chaque approche.

---

### **Chapitre 29 — Authentication et sécurité**

**Exercice 29.1** - Hashing de passwords  
Utilise `bcrypt` pour hasher les passwords : `.hash()` pour créer, `.compare()` pour vérifier. Ne JAMAIS stocker les passwords en clair.

**Exercice 29.2** - JWT basics  
Génère un JWT avec `jsonwebtoken` : `.sign(payload, secret)`. Vérifie avec `.verify()`. Comprends la structure (header.payload.signature).

**Exercice 29.3** - Authentication middleware  
Crée un middleware qui vérifie le JWT : lit le header Authorization, vérifie le token, attache les données user à `req.user`. Protège les routes.

**Exercice 29.4** - Refresh tokens  
Implémente un système de refresh tokens : access token court (15min), refresh token long (7j). Endpoint `/refresh` pour renouveler l'access token.

**Exercice 29.5** - Rate limiting  
Utilise `express-rate-limit` pour limiter les requêtes : max X requêtes par IP par fenêtre de temps. Prévient les attaques brute force.

**Exercice 29.6** - CORS  
Configure CORS avec `cors` middleware : autorise certaines origines, méthodes, headers. Comprends le Same-Origin Policy et comment CORS le contourne.

**Exercice 29.7** - Helmet  
Utilise `helmet` pour sécuriser les headers HTTP : CSP, HSTS, X-Frame-Options, etc. Une ligne de code pour beaucoup de sécurité.

**Exercice 29.8** - Input sanitization  
Sanitize toutes les entrées utilisateur : trim, escape HTML, valide les formats. Utilise des libraries comme `validator` et `express-validator`.

**Exercice 29.9** - HTTPS  
Configure HTTPS : génère un certificat (self-signed pour dev), utilise `https.createServer()` avec les certificats. En prod, utilise Let's Encrypt.

**Exercice 29.10** - Authentication complète  
Système d'auth complet : register (hash password), login (JWT), protected routes (middleware), refresh token, logout (blacklist token), password reset (email avec token temporaire).

---

## [GRAPHIQUE] PARTIE 7 — JavaScript avancé et optimisation

---

### **Chapitre 30 — Performance et optimisation**

**Exercice 30.1** - Mesure de performance  
Utilise `performance.now()` pour mesurer le temps d'exécution. Utilise `console.time()` et `console.timeEnd()`. Compare différentes implémentations.

**Exercice 30.2** - Optimisation de boucles  
Compare les performances de différentes boucles : for, forEach, for...of, map. Teste sur de grands tableaux. Cache la longueur dans une variable si possible.

**Exercice 30.3** - Debounce  
Implémente debounce : retarde l'exécution d'une fonction jusqu'à ce que X ms se soient écoulées sans nouvel appel. Utile pour search, scroll, resize.

**Exercice 30.4** - Throttle  
Implémente throttle : limite l'exécution à maximum une fois par X ms. Différent de debounce : s'exécute régulièrement pendant l'événement.

**Exercice 30.5** - Memoization  
Crée une fonction de memoization : cache les résultats des appels de fonction. Teste avec Fibonacci, calculs coûteux. Compare avec/sans cache.

**Exercice 30.6** - Lazy loading  
Implémente le lazy loading d'images : charge les images seulement quand elles entrent dans le viewport. Utilise IntersectionObserver.

**Exercice 30.7** - Virtual scrolling  
Pour de très grandes listes, implémente le virtual scrolling : rends seulement les éléments visibles. Complexe mais énorme gain de performance.

**Exercice 30.8** - Web Workers  
Utilise Web Workers pour déporter des calculs lourds sur un thread séparé. La page reste responsive pendant les calculs intensifs.

**Exercice 30.9** - Code splitting  
Avec un bundler (Vite, Webpack), implémente le code splitting : découpe ton code en chunks, charge dynamiquement (`import()`). Réduit le temps de chargement initial.

**Exercice 30.10** - Performance audit  
Audite une application : identifie les bottlenecks avec Chrome DevTools (Performance tab), optimise, mesure les gains. Crée un rapport d'optimisation.

---

### **Chapitre 31 — Memory management**

**Exercice 31.1** - Garbage collection  
Comprends le garbage collection en JS : mark-and-sweep algorithm. Les objets sans référence sont collectés. Teste en créant et perdant des références.

**Exercice 31.2** - Memory leaks  
Identifie les causes courantes de fuites mémoire : variables globales non intentionnelles, timers non cleared, event listeners non removed, closures qui retiennent des références.

**Exercice 31.3** - WeakMap pour caches  
Utilise WeakMap pour créer un cache qui ne cause pas de fuites mémoire : quand l'objet clé n'a plus de références, l'entrée est garbage collectée.

**Exercice 31.4** - Event listener cleanup  
Démontre une fuite mémoire avec des event listeners non nettoyés. Crée des éléments dynamiques avec listeners, supprime sans remove listeners. Puis corrige.

**Exercice 31.5** - Memory profiling  
Utilise Chrome DevTools Memory Profiler : prends des heap snapshots, compare, identifie ce qui grossit. Trouve les leaks avec Allocation Timeline.

**Exercice 31.6** - Large data handling  
Gère de grandes quantités de données efficacement : streaming plutôt que tout charger en mémoire, pagination, virtual scrolling, chunking.

**Exercice 31.7** - Object pooling  
Implémente l'object pooling : réutilise des objets plutôt que d'en créer/détruire constamment. Utile pour des objets créés fréquemment (particules, bullets dans un jeu).

**Exercice 31.8** - Détach DOM nodes  
Démontre que garder une référence à un DOM node détaché du document empêche sa garbage collection. Montre comment nettoyer proprement.

**Exercice 31.9** - Memory benchmarks  
Crée des benchmarks mémoire : compare l'empreinte mémoire de différentes approches (Map vs Object, Array vs Set, etc.). Utilise `performance.memory`.

**Exercice 31.10** - Memory optimization project  
Prends une app qui a des problèmes de mémoire. Profile, identifie les leaks, optimise, mesure. Documente les changements et gains.

---

### **Chapitre 32 — Testing**

**Exercice 32.1** - Premier test avec Jest  
Installe Jest. Crée ton premier test : teste une fonction simple. Utilise `expect()`, `.toBe()`, `.toEqual()`. Exécute avec `npm test`.

**Exercice 32.2** - Matchers  
Explore les matchers Jest : `.toBe()`, `.toEqual()`, `.toBeNull()`, `.toBeTruthy()`, `.toContain()`, `.toMatch()`, `.toBeGreaterThan()`, etc.

**Exercice 32.3** - Setup et teardown  
Utilise `beforeEach()`, `afterEach()`, `beforeAll()`, `afterAll()` pour setup/cleanup. Exemple : reset une DB, clear mocks, etc.

**Exercice 32.4** - Groupement de tests  
Organise les tests avec `describe()` pour grouper. Imbrique les `describe()` pour structure hiérarchique. Utilise `.only()` et `.skip()` pour exécution sélective.

**Exercice 32.5** - Testing async  
Teste du code async : retourne la Promise dans le test, ou utilise `async/await`. Jest attend automatiquement. Teste aussi les rejets.

**Exercice 32.6** - Mocking  
Utilise `jest.fn()` pour créer des mocks. Mock des modules avec `jest.mock()`. Vérifie les appels avec `.toHaveBeenCalled()`, `.toHaveBeenCalledWith()`.

**Exercice 32.7** - Spies  
Utilise `jest.spyOn()` pour espionner des méthodes sans changer leur implémentation. Vérifie qu'elles ont été appelées, avec quels arguments, combien de fois.

**Exercice 32.8** - Snapshot testing  
Teste des composants ou données avec snapshots : `.toMatchSnapshot()`. Crée un snapshot la première fois, compare les fois suivantes. Update avec `-u`.

**Exercice 32.9** - Coverage  
Génère un rapport de couverture : `jest --coverage`. Vise 80%+ de couverture. Identifie le code non testé. Configure les seuils minimums.

**Exercice 32.10** - TDD project  
Pratique le TDD (Test-Driven Development) : écris le test d'abord (il échoue), implémente le code minimum pour le faire passer, refactorise. Répète pour chaque feature.

---

### **Chapitre 33 — Debugging**

**Exercice 33.1** - Console methods  
Utilise toutes les méthodes console : `.log()`, `.error()`, `.warn()`, `.info()`, `.table()`, `.group()`, `.time()`, `.trace()`, `.assert()`.

**Exercice 33.2** - Debugger statement  
Utilise `debugger;` dans ton code pour créer un breakpoint programmatique. Le debugger du navigateur s'arrête là. Explore les variables, la stack.

**Exercice 33.3** - Chrome DevTools breakpoints  
Maîtrise les breakpoints : conditional breakpoints (s'arrête seulement si condition), logpoints (log sans arrêter), DOM breakpoints (sur modification DOM).

**Exercice 33.4** - Step debugging  
Utilise step over (F10), step into (F11), step out (Shift+F11) pour naviguer dans le code pas à pas. Comprends la différence entre chaque.

**Exercice 33.5** - Watch expressions  
Ajoute des watch expressions dans le debugger pour surveiller des variables/expressions. Elles se mettent à jour à chaque step.

**Exercice 33.6** - Network debugging  
Utilise l'onglet Network pour debugger les requêtes HTTP : status, headers, body, timing. Throttle la connexion pour simuler un réseau lent.

**Exercice 33.7** - Memory debugging  
Utilise Memory tab pour détecter les fuites : prends des snapshots, compare, identifie ce qui grossit. Utilise Allocation Timeline pour voir les allocations en temps réel.

**Exercice 33.8** - Performance profiling  
Profile ton app : enregistre pendant l'utilisation, analyse le flame graph, identifie les fonctions lentes, les long tasks. Optimise les bottlenecks.

**Exercice 33.9** - Source maps  
Configure les source maps pour debugger du code transpilé/minifié. En dev, ton code bundlé pointe vers le code source original.

**Exercice 33.10** - Remote debugging  
Debug une app mobile ou un device distant : active remote debugging, connecte Chrome DevTools. Debug sur le device réel plutôt que simulateur.

---

### **Chapitre 34 — TypeScript basics**

**Exercice 34.1** - Setup TypeScript  
Installe TypeScript : `npm install -D typescript`. Crée `tsconfig.json`. Compile avec `tsc`. Configure les options de base.

**Exercice 34.2** - Types de base  
Déclare des variables avec types : `let nom: string`, `let age: number`, `let actif: boolean`. Comprends l'inférence de type (TypeScript devine souvent).

**Exercice 34.3** - Fonctions typées  
Type les paramètres et le retour des fonctions : `function add(a: number, b: number): number`. Type optionnel : `param?:`, valeur par défaut : `param = valeur`.

**Exercice 34.4** - Interfaces  
Crée des interfaces pour typer des objets : `interface User { nom: string; age: number; }`. Utilise pour typer des paramètres, propriétés, etc.

**Exercice 34.5** - Types unions et intersections  
Utilise unions : `string | number`, intersections : `Type1 & Type2`. Narrowing avec typeof, instanceof, guards personnalisés.

**Exercice 34.6** - Types génériques  
Crée des fonctions/classes génériques : `function wrap<T>(value: T): T[]`. Utilise les generics pour du code réutilisable tout en gardant le typage fort.

**Exercice 34.7** - Enums  
Utilise des enums pour des constantes : `enum Status { Active, Inactive }`. Numeric enums (par défaut) vs string enums (plus safe).

**Exercice 34.8** - Type assertions  
Utilise les assertions de type quand tu sais mieux que TypeScript : `value as Type` ou `<Type>value`. À utiliser avec précaution.

**Exercice 34.9** - Classes TypeScript  
Déclare des classes avec types : propriétés typées, modificateurs (`public`, `private`, `readonly`), interfaces implémentées. Plus strict qu'en JS.

**Exercice 34.10** - Migration JS vers TS  
Prends un projet JavaScript. Migre progressivement vers TypeScript : renomme en `.ts`, ajoute des types progressivement, configure `allowJs`, fixe les erreurs.

---

### **Chapitre 35 — Tooling et Build**

**Exercice 35.1** - NPM basics  
Maîtrise npm : `npm init`, `npm install`, `npm install -D`, `package.json`, `package-lock.json`. Comprends les différences entre dependencies et devDependencies.

**Exercice 35.2** - Scripts NPM  
Crée des scripts dans `package.json` : `"start": "node server.js"`, `"test": "jest"`, etc. Lance avec `npm run script`. Chaîne des scripts.

**Exercice 35.3** - ESLint  
Configure ESLint : `npm init @eslint/config`. Choisis un style guide (Airbnb, Standard). Lint ton code, fixe automatiquement avec `--fix`.

**Exercice 35.4** - Prettier  
Installe Prettier pour le formatting automatique. Configure pour travailler avec ESLint (eslint-config-prettier). Format on save dans ton éditeur.

**Exercice 35.5** - Git hooks avec Husky  
Installe Husky pour Git hooks. Configure pre-commit pour linter/formatter avant chaque commit. Configure pre-push pour les tests.

**Exercice 35.6** - Vite  
Utilise Vite comme build tool : `npm create vite@latest`. Dev server ultra rapide (HMR instant), build optimisé, support TypeScript/JSX out of the box.

**Exercice 35.7** - Webpack basics  
Configure Webpack depuis zéro : entry, output, loaders, plugins. Comprends les concepts même si Vite est plus simple. Webpack reste pertinent pour des configs complexes.

**Exercice 35.8** - Babel  
Configure Babel pour transpiler du JS moderne vers du JS compatible vieux navigateurs. Configure les presets, plugins. Intègre avec ton build tool.

**Exercice 35.9** - Environment variables  
Gère les variables d'environnement : fichiers `.env`, `.env.local`, `.env.production`. Utilise `process.env` en