Objectifs de cette leçon
- Utiliser le spread et rest operator
- Maîtriser l'optional chaining
- Comprendre le nullish coalescing
ES6+ avance en JavaScript 🎯
ES6 (ES2015) et les versions suivantes ont apporte de nombreuses fonctionnalites qui rendent JavaScript plus moderne, concis et lisible.
1. Spread et Rest (...) 🌟
Spread (etaler)
// Tableaux const premier = [1, 2, 3]; const deuxieme = [4, 5, 6]; const fusion = [...premier, ...deuxieme]; // [1, 2, 3, 4, 5, 6] const copie = [...premier]; // Copie superficielle // Objets const base = { nom: "Alice", age: 25 }; const complet = { ...base, ville: "Paris" }; // { nom: "Alice", age: 25, ville: "Paris" } // Transformer une NodeList en tableau const paragraphs = [...document.querySelectorAll("p")];
Rest (rassembler)
// Dans les parametres function somme(premier, ...nombres) { return premier + nombres.reduce((a, b) => a + b, 0); } console.log(somme(1, 2, 3, 4, 5)); // 1 + 2 + 3 + 4 + 5 = 15 // Dans la destructuration const [tete, ...queue] = [1, 2, 3, 4]; console.log(tete); // 1 console.log(queue); // [2, 3, 4] const { nom, ...reste } = { nom: "Alice", age: 25, ville: "Paris" }; console.log(reste); // { age: 25, ville: "Paris" }
2. Optional chaining (?.) 🔗
Accede en securite a des proprietes imbriquees sans erreur :
const utilisateur = { nom: "Alice", adresse: { ville: "Paris", codePostal: "75001" } }; // ❌ Ancien — erreurs si une propriete est null/undefined const ville = utilisateur && utilisateur.adresse && utilisateur.adresse.ville; // ✅ ES2020 — Optional chaining const ville = utilisateur?.adresse?.ville; // "Paris" // Fonctions const resultat = utilisateur?.calculerScore?.(); // undefined si la methode n'existe pas // Tableaux const premier = tableau?.[0]; // undefined si tableau est null // Combinaison avec valeurs par defaut const ville = utilisateur?.adresse?.ville ?? "Inconnue";
| Cas | obj?.prop | Resultat |
|---|---|---|
| Objet normal | { a: 1 }?.a | 1 |
| Propriete manquante | { a: 1 }?.b | undefined |
| Objet null/undefined | null?.a | undefined |
| Objet vide | undefined?.a | undefined |
3. Nullish coalescing (??) 🤔
Operateur qui fournit une valeur par defaut UNIQUEMENT si la valeur est null ou undefined :
// ❌ || considere 0, "" et false comme "falsy" const nombre = 0 || 10; // 10 (pas bon si 0 est une valeur valide) const texte = "" || "defaut"; // "defaut" (pas bon si "" est voulu) // ✅ ?? ne considere que null et undefined const nombre = 0 ?? 10; // 0 (garde la valeur !) const texte = "" ?? "defaut"; // "" (garde la valeur !) // Cas d'utilisation const port = process.env.PORT ?? 3000; const nom = utilisateur.nom ?? "Anonyme";
| Expression | || | ?? |
|-----------|-------|-------|
| 0 || 10 | 10 | 0 |
| "" || "defaut" | "defaut" | "" |
| false || true | true | false |
| null || 5 | 5 | 5 |
| undefined || 5 | 5 | 5 |
4. Destructuration avancee 📦
Destructuration imbriquee
const personne = { nom: "Alice", coordonnees: { lat: 48.8566, lng: 2.3522 } }; const { nom, coordonnees: { lat, lng } } = personne; console.log(nom, lat, lng); // "Alice" 48.8566 2.3522
Destructuration dans une fonction
function afficherUtilisateur({ nom, age = 0, ville = "Inconnue" }) { return `${nom}, ${age} ans, ${ville}`; } console.log(afficherUtilisateur({ nom: "Alice", age: 25 })); // "Alice, 25 ans, Inconnue" console.log(afficherUtilisateur({ nom: "Bob", ville: "Lyon" })); // "Bob, 0 ans, Lyon"
Destructuration de tableau dans un objet
const [a, , c] = [1, 2, 3]; // Saute l'element 2 console.log(a, c); // 1 3
5. Template literals avanceses 🔧
const nom = "Alice"; const age = 25; // Interpolation console.log(`Bonjour ${nom}, tu as ${age} ans`); // Expressions dans l'interpolation console.log(`${nom} a ${age > 18 ? "la majorite" : "pas la majorite"}`); // Multi-lignes const html = ` <div class="card"> <h2>${nom}</h2> <p>Age : ${age}</p> </div> `; // Tagged templates (avance) function highlight(strings, ...values) { return strings.reduce((result, str, i) => { return result + str + (values[i] ? `${values[i]}` : ""); }, ""); } const highlighted = highlight`Bonjour ${nom}, tu as ${age} ans`; console.log(highlighted);
6. Class improvements 🏗️
class Animal { #nom; // Champ prive (ES2022) constructor(nom) { this.#nom = nom; } get nom() { return this.#nom; } static creer(nom) { return new Animal(nom); } saluer() { return `Je suis ${this.#nom}`; } } class Chien extends Animal { #race; constructor(nom, race) { super(nom); this.#race = race; } aboyer() { return `${this.nom} aboie !`; } } const rex = new Chien("Rex", "Labrador"); console.log(rex.aboyer()); // "Rex aboie !"
7. Promise.any et Promise.allSettled 🛡️
// Promise.allSettled — pas d'echec global const resultats = await Promise.allSettled([ Promise.resolve("OK"), Promise.reject("Erreur"), Promise.resolve("OK 2") ]); // resultats = [ // { status: "fulfilled", value: "OK" }, // { status: "rejected", reason: "Erreur" }, // { status: "fulfilled", value: "OK 2" } // ] // Promise.any — le premier succes gagne const premier = await Promise.any([ fetch("https://api1.example.com").then(r => r.json()), fetch("https://api2.example.com").then(r => r.json()) ]);
8. Object.groupBy et Map 🗺️
// Object.groupBy — grouper un tableau const personnes = [ { nom: "Alice", ville: "Paris" }, { nom: "Bob", ville: "Lyon" }, { nom: "Charlie", ville: "Paris" } ]; const parVille = Object.groupBy(personnes, p => p.ville); console.log(parVille); // { // Paris: [{ nom: "Alice", ... }, { nom: "Charlie", ... }], // Lyon: [{ nom: "Bob", ... }] // }
9. Structured clone et other modernes 🧰
// Deep copy moderne const original = { a: { b: { c: 1 } } }; const copie = structuredClone(original); copie.a.b.c = 2; console.log(original.a.b.c); // 1 — intact // Array.from — creer un tableau const lettres = Array.from("hello", l => l.toUpperCase()); console.log(lettres); // ["H", "E", "L", "L", "O"] // Array.at — acceder avec index negatif const tab = [1, 2, 3, 4, 5]; console.log(tab.at(-1)); // 5 console.log(tab.at(-2)); // 4 // at() aussi pour les chaines const str = "Bonjour"; console.log(str.at(-1)); // "r"
10. Resumé des features ES6+ ⚙️
| Feature | Version | Description |
|---|---|---|
let / const | ES6 | Variables a portee de bloc |
| Arrow functions | ES6 | x => x * 2 |
| Template literals | ES6 | `Bonjour ${nom}` |
| Destructuration | ES6 | const { a, b } = obj |
| Spread/Rest | ES6 | ...obj, ...args |
| Default params | ES6 | function(a = 1) |
| Classes | ES6 | class X {} |
| Modules | ES6 | import/export |
| Optional chaining | ES2020 | obj?.prop |
| Nullish coalescing | ES2020 | x ?? "defaut" |
| Private fields | ES2022 | #champ |
| Array.at() | ES2023 | tab.at(-1) |
| structuredClone | ES2022 | Deep copy |
| Object.groupBy | ES2024 | Grouper par critere |
11. Exercices pour toi 🎯
Exercice 1 : Merge profond
Cree une fonction fusionnerProfond(a, b) qui fusionne deux objets imbriques sans spread superficial.
Exercice 2 : Debounce
Implemente une fonction debounce(fn, ms) avec closures et parametres par defaut.
Exercice 3 : Pipeline
Cree une fonction pipeline(...fns) qui applique des fonctions de gauche a droite :
const ajouter1 = x => x + 1; const doubler = x => x * 2; const pipeline = pipeline(ajouter1, doubler); pipeline(3); // (3 + 1) * 2 = 8
⚡ Simulateur — ES6+ avancé
Étape 1/6arr1 est un tableau de 3 nombres. On va utiliser les fonctionnalités ES6+ pour le manipuler de façon moderne.