0 XP
?
Intermédiaire40 min25 XP

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";
Casobj?.propResultat
Objet normal{ a: 1 }?.a1
Propriete manquante{ a: 1 }?.bundefined
Objet null/undefinednull?.aundefined
Objet videundefined?.aundefined

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+ ⚙️

FeatureVersionDescription
let / constES6Variables a portee de bloc
Arrow functionsES6x => x * 2
Template literalsES6`Bonjour ${nom}`
DestructurationES6const { a, b } = obj
Spread/RestES6...obj, ...args
Default paramsES6function(a = 1)
ClassesES6class X {}
ModulesES6import/export
Optional chainingES2020obj?.prop
Nullish coalescingES2020x ?? "defaut"
Private fieldsES2022#champ
Array.at()ES2023tab.at(-1)
structuredCloneES2022Deep copy
Object.groupByES2024Grouper 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/6
📝 Pseudo-code
1const arr1 = [1, 2, 3];
2const arr2 = [...arr1, 4, 5];
3const [a, b, ...rest] = arr2;
4console.log(a, b, rest);
5const name = null ?? "Anonyme";
6console.log(name);
⚙️ Exécution
📦 Mémoire
arr1
[1, 2, 3]
🔀 Flux d'exécution
arr1 = [1,2,3]
3
Tableau original

arr1 est un tableau de 3 nombres. On va utiliser les fonctionnalités ES6+ pour le manipuler de façon moderne.