📦 Structures de Données

JavaScript

Manipuler tableaux, objets et données

Formation DWWM - 2026

Au programme 📋

# 📚 Partie 0

Rappel : Tableaux et Objets

Les structures de données de base

C'est quoi un tableau ? 📋

Un tableau (array) est une liste ordonnée de valeurs.

Analogie : Le casier à bouteilles 🍾

Imagine un casier avec plusieurs emplacements numérotés (0, 1, 2, 3...). Chaque emplacement peut contenir une bouteille différente. Tu peux accéder à une bouteille spécifique en connaissant son numéro !

// Créer un tableau
const fruits = ["pomme", "banane", "orange", "kiwi"];

// Accéder aux éléments (index commence à 0)
console.log(fruits[0]);  // "pomme"
console.log(fruits[1]);  // "banane"
console.log(fruits[2]);  // "orange"

// Nombre d'éléments
console.log(fruits.length);  // 4

// Dernier élément
console.log(fruits[fruits.length - 1]);  // "kiwi"
Index: 0 1 2 3
Valeur: ["pomme", "banane", "orange", "kiwi"]

C'est quoi un objet ? 🎯

Un objet est une collection de propriétés (paires clé-valeur).

Analogie : La carte d'identité 🪪

Un objet est comme une carte d'identité : elle contient différentes informations (nom, prénom, âge...) avec des étiquettes. Chaque étiquette (clé) est associée à une valeur.

// Créer un objet
const personne = {
    nom: "Dupont",
    prenom: "Marie",
    age: 25,
    ville: "Paris"
};

// Accéder aux propriétés
console.log(personne.nom);     // "Dupont"
console.log(personne.prenom);  // "Marie"
console.log(personne["age"]);  // 25 (notation alternative)

// Modifier une propriété
personne.age = 26;

// Ajouter une propriété
personne.email = "marie@example.com";
{
clé1: valeur1,
clé2: valeur2,
clé3: valeur3
}

Tableau vs Objet 🆚

Caractéristique Tableau Objet
Structure Liste ordonnée Collection clé-valeur
Accès Par index numérique (0, 1, 2...) Par nom de propriété
Ordre Oui, important Non garanti
Usage Liste d'éléments similaires Décrire une entité
Exemple ["pomme", "banane"] {nom: "Marie", age: 25}

Quand utiliser un tableau ?

  • Liste de courses
  • Liste d'étudiants
  • Résultats de recherche
  • Données ordonnées

Quand utiliser un objet ?

  • Profil utilisateur
  • Configuration
  • Données d'une personne
  • Propriétés nommées
# 🗺️ Partie 1

Méthodes de Tableaux

Transformer et manipuler les données

Méthodes de tableaux : Pourquoi ? 💡

Les méthodes de tableaux permettent de transformer, filtrer et manipuler les données facilement.

❌ Ancienne méthode (boucle for)

const nombres = [1, 2, 3, 4, 5];
const doubles = [];

for (let i = 0; i < nombres.length; i++) {
    doubles.push(nombres[i] * 2);
}

console.log(doubles);
// [2, 4, 6, 8, 10]

// 😰 Verbeux et répétitif !

✅ Méthode moderne (map)

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

const doubles = nombres.map(n => n * 2);

console.log(doubles);
// [2, 4, 6, 8, 10]

// ✨ Simple et clair !

Avantages des méthodes :

forEach : Parcourir un tableau 🔄

forEach exécute une fonction pour chaque élément du tableau.

tableau.forEach((element, index) => {
// Code à exécuter pour chaque élément
});
// Exemple simple
const fruits = ["pomme", "banane", "orange"];

fruits.forEach((fruit) => {
    console.log(fruit);
});
// "pomme"
// "banane"
// "orange"

// Avec l'index
fruits.forEach((fruit, index) => {
    console.log(`${index}: ${fruit}`);
});
// 0: pomme
// 1: banane
// 2: orange

// Cas d'usage : afficher une liste
const produits = ["Ordinateur", "Souris", "Clavier"];

produits.forEach((produit, i) => {
    console.log(`${i + 1}. ${produit}`);
});
// 1. Ordinateur
// 2. Souris
// 3. Clavier

⚠️ Important : forEach ne retourne RIEN. Utilise-le juste pour exécuter du code, pas pour transformer un tableau.

map : Transformer chaque élément 🗺️

map crée un nouveau tableau en transformant chaque élément.

Analogie : L'usine 🏭

Imagine une usine : tu mets des matières premières sur un tapis roulant, elles passent dans une machine qui les transforme, et tu récupères les produits finis de l'autre côté. C'est exactement map !

const nouveauTableau = tableau.map((element) => {
return elementTransformé;
});
// Doubler chaque nombre
const nombres = [1, 2, 3, 4, 5];

const doubles = nombres.map(n => n * 2);

console.log(doubles);  // [2, 4, 6, 8, 10]
console.log(nombres);  // [1, 2, 3, 4, 5] (original inchangé)

// Extraire une propriété d'objets
const utilisateurs = [
    {nom: "Marie", age: 25},
    {nom: "Jean", age: 30},
    {nom: "Paul", age: 28}
];

const noms = utilisateurs.map(user => user.nom);
console.log(noms);  // ["Marie", "Jean", "Paul"]

const ages = utilisateurs.map(user => user.age);
console.log(ages);  // [25, 30, 28]

// Transformer en HTML
const fruits = ["pomme", "banane", "orange"];

const listeHTML = fruits.map(fruit => `
  • ${fruit}
  • `); console.log(listeHTML); // ["
  • pomme
  • ", "
  • banane
  • ", "
  • orange
  • "]

    map : Comment ça marche ? ⚙️

    1. map parcourt chaque élément
      Comme une boucle, mais automatique
    2. Applique la fonction à chaque élément
      Ta fonction reçoit l'élément et le transforme
    3. Crée un nouveau tableau avec les résultats
      Le tableau original reste intact
    [1, 2, 3]
    ↓ map(n => n * 2)
    [1*2, 2*2, 3*2]
    ↓
    [2, 4, 6]
    // Exemple détaillé
    const prix = [10, 20, 30];
    
    const prixAvecTVA = prix.map((p) => {
        console.log(`Traitement de ${p}`);
        const avecTVA = p * 1.20;
        console.log(`Résultat: ${avecTVA}`);
        return avecTVA;
    });
    
    // Console :
    // Traitement de 10
    // Résultat: 12
    // Traitement de 20
    // Résultat: 24
    // Traitement de 30
    // Résultat: 36
    
    console.log(prixAvecTVA);  // [12, 24, 36]

    Règle d'or : map retourne TOUJOURS un tableau de la MÊME longueur que l'original.

    filter : Filtrer les éléments 🔍

    filter crée un nouveau tableau contenant uniquement les éléments qui passent un test.

    Analogie : Le tamis 🥅

    Imagine un tamis qui laisse passer certains éléments et en bloque d'autres selon un critère. C'est filter : tu définis le critère, et seuls les éléments qui le respectent passent !

    const nouveauTableau = tableau.filter((element) => {
    return condition; // true = gardé, false = éliminé
    });
    // Garder uniquement les nombres pairs
    const nombres = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    
    const pairs = nombres.filter(n => n % 2 === 0);
    
    console.log(pairs);  // [2, 4, 6, 8, 10]
    
    // Garder uniquement les majeurs
    const ages = [12, 18, 25, 15, 30, 17, 21];
    
    const majeurs = ages.filter(age => age >= 18);
    
    console.log(majeurs);  // [18, 25, 30, 21]
    
    // Filtrer des objets
    const produits = [
        {nom: "PC", prix: 800},
        {nom: "Souris", prix: 20},
        {nom: "Écran", prix: 300},
        {nom: "Clavier", prix: 50}
    ];
    
    const produitsChers = produits.filter(p => p.prix > 100);
    
    console.log(produitsChers);
    // [{nom: "PC", prix: 800}, {nom: "Écran", prix: 300}]

    filter : Comment ça marche ? ⚙️

    1. filter parcourt chaque élément
      Un par un, dans l'ordre
    2. Teste chaque élément avec ta condition
      Ta fonction doit retourner true ou false
    3. Garde uniquement les true
      Crée un nouveau tableau avec les éléments validés
    [1, 2, 3, 4, 5]
    ↓ filter(n => n > 2)
    [false, false, true, true, true]
    ↓
    [3, 4, 5]
    // Exemple avec logs
    const notes = [8, 15, 12, 18, 9, 14];
    
    const notesSupA10 = notes.filter((note) => {
        console.log(`Test de ${note} > 10 : ${note > 10}`);
        return note > 10;
    });
    
    // Console :
    // Test de 8 > 10 : false
    // Test de 15 > 10 : true
    // Test de 12 > 10 : true
    // Test de 18 > 10 : true
    // Test de 9 > 10 : false
    // Test de 14 > 10 : true
    
    console.log(notesSupA10);  // [15, 12, 18, 14]

    Règle : filter retourne un tableau de longueur inférieure ou égale à l'original.

    reduce : Réduire à une seule valeur 📉

    reduce réduit un tableau à une seule valeur (nombre, string, objet...).

    Analogie : La boule de neige ⛄

    Imagine que tu roules une boule de neige : tu commences avec une petite boule (valeur initiale), et à chaque tour, tu rajoutes de la neige (chaque élément). À la fin, tu as UNE grosse boule qui contient tout !

    const resultat = tableau.reduce((accumulateur, element) => {
    return nouvelAccumulateur;
    }, valeurInitiale);
    // Additionner tous les nombres
    const nombres = [1, 2, 3, 4, 5];
    
    const somme = nombres.reduce((acc, n) => {
        return acc + n;
    }, 0);  // 0 = valeur initiale
    
    console.log(somme);  // 15
    
    // Version courte
    const total = nombres.reduce((acc, n) => acc + n, 0);
    
    // Trouver le maximum
    const max = nombres.reduce((acc, n) => {
        return n > acc ? n : acc;
    }, nombres[0]);
    
    console.log(max);  // 5

    reduce : Comment ça marche ? ⚙️

    Suivons étape par étape ce qui se passe :

    const nombres = [1, 2, 3, 4];
    
    const somme = nombres.reduce((acc, n) => {
        console.log(`acc: ${acc}, n: ${n}, nouveau acc: ${acc + n}`);
        return acc + n;
    }, 0);
    
    // Console :
    // acc: 0, n: 1, nouveau acc: 1
    // acc: 1, n: 2, nouveau acc: 3
    // acc: 3, n: 3, nouveau acc: 6
    // acc: 6, n: 4, nouveau acc: 10
    
    console.log(somme);  // 10
    Étape 0 : acc = 0 (valeur initiale)
    Étape 1 : acc = 0 + 1 = 1
    Étape 2 : acc = 1 + 2 = 3
    Étape 3 : acc = 3 + 3 = 6
    Étape 4 : acc = 6 + 4 = 10
    Résultat final : 10
    1. Commence avec la valeur initiale
      C'est ton point de départ
    2. Pour chaque élément
      Combine l'accumulateur avec l'élément
    3. Met à jour l'accumulateur
      Le résultat devient le nouvel accumulateur
    4. Retourne la valeur finale
      Après avoir traité tous les éléments

    reduce : Cas d'usage avancés 🎯

    Compter les occurrences

    const fruits = ["pomme", "banane", "pomme", "orange", "banane", "pomme"];
    
    const compteur = fruits.reduce((acc, fruit) => {
        acc[fruit] = (acc[fruit] || 0) + 1;
        return acc;
    }, {});
    
    console.log(compteur);
    // {pomme: 3, banane: 2, orange: 1}

    Calculer un total de prix

    const panier = [
        {produit: "PC", prix: 800, qte: 1},
        {produit: "Souris", prix: 20, qte: 2},
        {produit: "Clavier", prix: 50, qte: 1}
    ];
    
    const total = panier.reduce((acc, item) => {
        return acc + (item.prix * item.qte);
    }, 0);
    
    console.log(total);  // 800 + 40 + 50 = 890

    Aplatir un tableau de tableaux

    const tableaux = [[1, 2], [3, 4], [5, 6]];
    
    const aplati = tableaux.reduce((acc, tab) => {
        return acc.concat(tab);
    }, []);
    
    console.log(aplati);  // [1, 2, 3, 4, 5, 6]

    find et findIndex : Trouver un élément 🔎

    find : Trouver le premier élément qui match

    const utilisateurs = [
        {id: 1, nom: "Marie"},
        {id: 2, nom: "Jean"},
        {id: 3, nom: "Paul"}
    ];
    
    const user = utilisateurs.find(u => u.id === 2);
    
    console.log(user);  // {id: 2, nom: "Jean"}
    
    const introuvable = utilisateurs.find(u => u.id === 99);
    console.log(introuvable);  // undefined

    findIndex : Trouver l'index du premier élément

    const nombres = [10, 20, 30, 40, 50];
    
    const index = nombres.findIndex(n => n > 25);
    
    console.log(index);  // 2 (l'index de 30)
    
    const indexIntrouvable = nombres.findIndex(n => n > 100);
    console.log(indexIntrouvable);  // -1 (pas trouvé)

    find

    Retourne l'élément trouvé ou undefined

    findIndex

    Retourne l'index trouvé ou -1

    some et every : Tester les éléments ✅

    some : Au moins UN élément valide le test ?

    const ages = [12, 15, 18, 20];
    
    // Y a-t-il au moins un majeur ?
    const unMajeur = ages.some(age => age >= 18);
    console.log(unMajeur);  // true
    
    // Y a-t-il au moins un enfant (< 12) ?
    const unEnfant = ages.some(age => age < 12);
    console.log(unEnfant);  // false

    every : TOUS les éléments valident le test ?

    const notes = [12, 15, 18, 14];
    
    // Toutes les notes sont-elles > 10 ?
    const toutesSupA10 = notes.every(note => note > 10);
    console.log(toutesSupA10);  // true
    
    // Toutes les notes sont-elles > 15 ?
    const toutesSupA15 = notes.every(note => note > 15);
    console.log(toutesSupA15);  // false (12 et 14 ne passent pas)
    Méthode Question Retourne true si
    some Au moins un ? ≥ 1 élément valide
    every Tous ? TOUS les éléments valident

    Chaînage de méthodes 🔗

    On peut enchaîner plusieurs méthodes pour des transformations complexes !

    const nombres = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    
    // Filtrer les pairs, les doubler, puis additionner
    const resultat = nombres
        .filter(n => n % 2 === 0)    // [2, 4, 6, 8, 10]
        .map(n => n * 2)              // [4, 8, 12, 16, 20]
        .reduce((acc, n) => acc + n, 0);  // 60
    
    console.log(resultat);  // 60

    Exemple complet avec objets

    const produits = [
        {nom: "PC", prix: 800, categorie: "informatique"},
        {nom: "Souris", prix: 20, categorie: "informatique"},
        {nom: "Chaise", prix: 150, categorie: "mobilier"},
        {nom: "Écran", prix: 300, categorie: "informatique"},
        {nom: "Bureau", prix: 400, categorie: "mobilier"}
    ];
    
    // Trouver le total des produits informatiques > 50€
    const total = produits
        .filter(p => p.categorie === "informatique")  // Seulement informatique
        .filter(p => p.prix > 50)                     // Plus de 50€
        .map(p => p.prix)                             // Extraire les prix
        .reduce((acc, prix) => acc + prix, 0);        // Additionner
    
    console.log(total);  // 800 + 300 = 1100
    
    // Même chose en une ligne
    const total2 = produits
        .filter(p => p.categorie === "informatique" && p.prix > 50)
        .reduce((acc, p) => acc + p.prix, 0);
    
    console.log(total2);  // 1100

    Récapitulatif des méthodes 📚

    Méthode Action Retourne Exemple
    forEach Parcourir Rien arr.forEach(x => console.log(x))
    map Transformer Nouveau tableau arr.map(x => x * 2)
    filter Filtrer Nouveau tableau arr.filter(x => x > 10)
    reduce Réduire Une valeur arr.reduce((a,x) => a+x, 0)
    find Trouver Élément ou undefined arr.find(x => x.id === 2)
    findIndex Trouver index Index ou -1 arr.findIndex(x => x > 5)
    some Tester (≥1) Boolean arr.some(x => x > 10)
    every Tester (tous) Boolean arr.every(x => x > 0)
    # 🎯 Partie 2

    Manipulation d'Objets

    Créer et manipuler des objets

    Créer des objets 🏗️

    1. Littéral d'objet (le plus courant)

    const personne = {
        nom: "Dupont",
        prenom: "Marie",
        age: 25
    };
    
    // Objet vide
    const vide = {};

    2. Avec new Object() (déprécié)

    const personne = new Object();
    personne.nom = "Dupont";
    personne.prenom = "Marie";

    3. Propriétés calculées

    const cle = "email";
    const valeur = "marie@example.com";
    
    const personne = {
        nom: "Marie",
        [cle]: valeur  // Propriété dynamique
    };
    
    console.log(personne);
    // {nom: "Marie", email: "marie@example.com"}

    4. Raccourci de propriété (shorthand)

    const nom = "Marie";
    const age = 25;
    
    // Ancienne méthode
    const personne1 = {nom: nom, age: age};
    
    // Méthode courte (ES6)
    const personne2 = {nom, age};  // ✅ Identique !
    
    console.log(personne2);  // {nom: "Marie", age: 25}

    Accéder aux propriétés 🔑

    Notation point (la plus courante)

    const personne = {
        nom: "Dupont",
        prenom: "Marie",
        age: 25
    };
    
    console.log(personne.nom);     // "Dupont"
    console.log(personne.prenom);  // "Marie"

    Notation crochet

    console.log(personne["nom"]);  // "Dupont"
    console.log(personne["age"]);  // 25
    
    // Utile avec une variable
    const propriete = "prenom";
    console.log(personne[propriete]);  // "Marie"
    
    // Utile avec des espaces ou caractères spéciaux
    const config = {
        "clé avec espaces": "valeur",
        "clé-avec-tirets": "autre valeur"
    };
    
    console.log(config["clé avec espaces"]);  // "valeur"

    Notation point

    ✅ Plus lisible

    ❌ Uniquement si le nom est connu et valide

    Notation crochet

    ✅ Propriété dynamique

    ✅ Noms avec espaces/caractères spéciaux

    Modifier et ajouter des propriétés ✏️

    const personne = {
        nom: "Dupont",
        age: 25
    };
    
    // Modifier une propriété existante
    personne.age = 26;
    console.log(personne.age);  // 26
    
    // Ajouter une nouvelle propriété
    personne.ville = "Paris";
    console.log(personne);
    // {nom: "Dupont", age: 26, ville: "Paris"}
    
    // Ajouter plusieurs propriétés
    personne.email = "marie@example.com";
    personne.telephone = "0123456789";
    
    // Supprimer une propriété
    delete personne.telephone;
    console.log(personne);
    // {nom: "Dupont", age: 26, ville: "Paris", email: "marie@example.com"}

    ⚠️ Attention : En JavaScript, on peut toujours ajouter/modifier des propriétés, même avec const ! const empêche juste de réassigner la variable entière.

    const obj = {x: 1};
    obj.y = 2;  // ✅ OK
    obj = {};   // ❌ ERREUR : réassignation interdite

    Méthodes d'objet 🛠️

    Un objet peut contenir des fonctions (appelées méthodes).

    const personne = {
        nom: "Dupont",
        prenom: "Marie",
        age: 25,
        
        // Méthode (fonction dans un objet)
        sePresenter() {
            return `Je suis ${this.prenom} ${this.nom}, j'ai ${this.age} ans`;
        },
        
        vieillir() {
            this.age++;
        }
    };
    
    console.log(personne.sePresenter());
    // "Je suis Marie Dupont, j'ai 25 ans"
    
    personne.vieillir();
    console.log(personne.age);  // 26

    Le mot-clé this

    this fait référence à l'objet lui-même. Il permet d'accéder aux autres propriétés de l'objet.

    const calculatrice = {
        a: 10,
        b: 5,
        
        additionner() {
            return this.a + this.b;
        },
        
        multiplier() {
            return this.a * this.b;
        }
    };
    
    console.log(calculatrice.additionner());  // 15
    console.log(calculatrice.multiplier());   // 50

    Parcourir un objet 🔄

    1. for...in : Parcourir les clés

    const personne = {
        nom: "Dupont",
        prenom: "Marie",
        age: 25
    };
    
    for (let cle in personne) {
        console.log(cle, ":", personne[cle]);
    }
    // nom : Dupont
    // prenom : Marie
    // age : 25

    2. Object.keys() : Obtenir un tableau des clés

    const cles = Object.keys(personne);
    console.log(cles);  // ["nom", "prenom", "age"]
    
    cles.forEach(cle => {
        console.log(`${cle}: ${personne[cle]}`);
    });

    3. Object.values() : Obtenir un tableau des valeurs

    const valeurs = Object.values(personne);
    console.log(valeurs);  // ["Dupont", "Marie", 25]

    4. Object.entries() : Obtenir un tableau de paires [clé, valeur]

    const entrees = Object.entries(personne);
    console.log(entrees);
    // [["nom", "Dupont"], ["prenom", "Marie"], ["age", 25]]
    
    entrees.forEach(([cle, valeur]) => {
        console.log(`${cle}: ${valeur}`);
    });

    Copier un objet 📋

    Attention : les objets sont copiés par référence !

    ⚠️ Piège : Copie par référence

    const original = {nom: "Marie", age: 25};
    
    const copie = original;  // ❌ Ce n'est PAS une copie !
    
    copie.age = 30;
    
    console.log(original.age);  // 30 ← L'original est modifié !
    console.log(copie.age);     // 30
    
    // Ils pointent vers le MÊME objet en mémoire

    ✅ Solution 1 : Object.assign()

    const original = {nom: "Marie", age: 25};
    
    const copie = Object.assign({}, original);
    
    copie.age = 30;
    
    console.log(original.age);  // 25 ← Inchangé !
    console.log(copie.age);     // 30

    ✅ Solution 2 : Spread operator (plus moderne)

    const original = {nom: "Marie", age: 25};
    
    const copie = {...original};
    
    copie.age = 30;
    
    console.log(original.age);  // 25 ← Inchangé !
    console.log(copie.age);     // 30

    Fusionner des objets 🔀

    Avec Object.assign()

    const obj1 = {a: 1, b: 2};
    const obj2 = {c: 3, d: 4};
    
    const fusion = Object.assign({}, obj1, obj2);
    
    console.log(fusion);  // {a: 1, b: 2, c: 3, d: 4}

    Avec le spread operator (plus moderne)

    const obj1 = {a: 1, b: 2};
    const obj2 = {c: 3, d: 4};
    
    const fusion = {...obj1, ...obj2};
    
    console.log(fusion);  // {a: 1, b: 2, c: 3, d: 4}
    
    // En cas de conflit, le dernier gagne
    const config1 = {port: 3000, debug: true};
    const config2 = {port: 8080, host: "localhost"};
    
    const config = {...config1, ...config2};
    
    console.log(config);
    // {port: 8080, debug: true, host: "localhost"}
    // port a été écrasé par config2
    # 📤 Partie 3

    Destructuration

    Extraire des valeurs facilement

    Destructuration de tableaux 📦

    La destructuration permet d'extraire des valeurs d'un tableau et de les assigner à des variables.

    ❌ Sans destructuration

    const fruits = ["pomme", "banane", "orange"];
    
    const fruit1 = fruits[0];
    const fruit2 = fruits[1];
    const fruit3 = fruits[2];
    
    console.log(fruit1);  // "pomme"

    ✅ Avec destructuration

    const fruits = ["pomme", "banane", "orange"];
    
    const [fruit1, fruit2, fruit3] = fruits;
    
    console.log(fruit1);  // "pomme"
    console.log(fruit2);  // "banane"

    Ignorer des éléments

    const nombres = [1, 2, 3, 4, 5];
    
    const [premier, , troisieme] = nombres;
    
    console.log(premier);   // 1
    console.log(troisieme); // 3  (on a sauté le 2)

    Avec valeurs par défaut

    const tableau = [10];
    
    const [a, b = 20, c = 30] = tableau;
    
    console.log(a);  // 10
    console.log(b);  // 20 (valeur par défaut)
    console.log(c);  // 30 (valeur par défaut)

    Rest dans la destructuration 📦

    On peut utiliser ... pour récupérer le reste des éléments.

    const nombres = [1, 2, 3, 4, 5];
    
    const [premier, deuxieme, ...reste] = nombres;
    
    console.log(premier);   // 1
    console.log(deuxieme);  // 2
    console.log(reste);     // [3, 4, 5]
    
    // Autre exemple
    const [a, ...tous] = [10, 20, 30, 40];
    
    console.log(a);     // 10
    console.log(tous);  // [20, 30, 40]

    Échanger deux variables

    let a = 1;
    let b = 2;
    
    // Ancienne méthode (avec variable temporaire)
    let temp = a;
    a = b;
    b = temp;
    
    // Avec destructuration (moderne)
    [a, b] = [b, a];
    
    console.log(a);  // 2
    console.log(b);  // 1

    Destructuration d'objets 🎯

    Même principe avec les objets : extraire des propriétés dans des variables.

    ❌ Sans destructuration

    const personne = {
        nom: "Dupont",
        prenom: "Marie",
        age: 25
    };
    
    const nom = personne.nom;
    const prenom = personne.prenom;
    const age = personne.age;

    ✅ Avec destructuration

    const personne = {
        nom: "Dupont",
        prenom: "Marie",
        age: 25
    };
    
    const {nom, prenom, age} = personne;
    
    console.log(nom);  // "Dupont"

    Important : Les noms des variables doivent correspondre aux noms des propriétés !

    // Extraire seulement certaines propriétés
    const user = {
        id: 1,
        nom: "Marie",
        email: "marie@example.com",
        age: 25,
        ville: "Paris"
    };
    
    const {nom, email} = user;
    
    console.log(nom);    // "Marie"
    console.log(email);  // "marie@example.com"

    Renommer et valeurs par défaut 🔧

    Renommer une variable

    const personne = {
        nom: "Dupont",
        prenom: "Marie"
    };
    
    // Renommer nom en nomFamille
    const {nom: nomFamille, prenom} = personne;
    
    console.log(nomFamille);  // "Dupont"
    console.log(prenom);      // "Marie"
    // console.log(nom);      // ❌ Erreur : nom n'existe pas

    Valeurs par défaut

    const config = {
        host: "localhost",
        port: 3000
    };
    
    const {host, port, debug = false} = config;
    
    console.log(host);   // "localhost"
    console.log(port);   // 3000
    console.log(debug);  // false (valeur par défaut)

    Combiner renommage et défaut

    const user = {
        name: "Marie"
    };
    
    const {name: prenom, age: utilisateurAge = 18} = user;
    
    console.log(prenom);          // "Marie"
    console.log(utilisateurAge);  // 18 (défaut)

    Destructuration imbriquée 🪆

    On peut destructurer des objets/tableaux imbriqués !

    const utilisateur = {
        nom: "Marie",
        adresse: {
            rue: "123 Rue de la Paix",
            ville: "Paris",
            codePostal: "75001"
        },
        hobbies: ["lecture", "sport"]
    };
    
    // Destructurer l'objet imbriqué
    const {
        nom,
        adresse: {ville, codePostal},
        hobbies: [hobby1, hobby2]
    } = utilisateur;
    
    console.log(nom);         // "Marie"
    console.log(ville);       // "Paris"
    console.log(codePostal);  // "75001"
    console.log(hobby1);      // "lecture"
    console.log(hobby2);      // "sport"
    
    // ⚠️ Attention : adresse n'existe pas, seulement ville et codePostal
    // console.log(adresse);  // ❌ Erreur

    ⚠️ Attention : Si tu destructures un objet imbriqué, seules les propriétés extraites sont créées comme variables, pas l'objet parent !

    Destructuration dans les paramètres 🎯

    Très utile pour les fonctions qui reçoivent des objets !

    ❌ Sans destructuration

    function afficherUser(user) {
        console.log(user.nom);
        console.log(user.age);
        console.log(user.ville);
    }
    
    afficherUser({
        nom: "Marie",
        age: 25,
        ville: "Paris"
    });

    ✅ Avec destructuration

    function afficherUser({nom, age, ville}) {
        console.log(nom);
        console.log(age);
        console.log(ville);
    }
    
    afficherUser({
        nom: "Marie",
        age: 25,
        ville: "Paris"
    });

    Avec valeurs par défaut

    function creerUser({nom, age, role = "utilisateur"}) {
        return {nom, age, role};
    }
    
    console.log(creerUser({nom: "Marie", age: 25}));
    // {nom: "Marie", age: 25, role: "utilisateur"}

    Exemple pratique : configuration

    function demarrerServeur({
        port = 3000,
        host = "localhost",
        debug = false
    }) {
        console.log(`Serveur démarré sur ${host}:${port}`);
        console.log(`Mode debug: ${debug}`);
    }
    
    demarrerServeur({port: 8080});
    // Serveur démarré sur localhost:8080
    // Mode debug: false
    # ✨ Partie 4

    Spread Operator

    Déployer et combiner (...)

    Spread avec les tableaux ✨

    Le spread operator (...) permet de "déployer" les éléments d'un tableau.

    Copier un tableau

    const original = [1, 2, 3];
    
    const copie = [...original];
    
    copie.push(4);
    
    console.log(original);  // [1, 2, 3] (inchangé)
    console.log(copie);     // [1, 2, 3, 4]

    Combiner des tableaux

    const fruits = ["pomme", "banane"];
    const legumes = ["carotte", "tomate"];
    
    const aliments = [...fruits, ...legumes];
    
    console.log(aliments);
    // ["pomme", "banane", "carotte", "tomate"]
    
    // Ajouter des éléments au milieu
    const nouveaux = [...fruits, "orange", ...legumes];
    console.log(nouveaux);
    // ["pomme", "banane", "orange", "carotte", "tomate"]

    Passer comme arguments de fonction

    const nombres = [5, 12, 3, 99, 42];
    
    // Ancienne méthode
    const max1 = Math.max.apply(null, nombres);
    
    // Avec spread (moderne)
    const max2 = Math.max(...nombres);
    
    console.log(max2);  // 99

    Spread avec les objets ✨

    Copier un objet

    const original = {nom: "Marie", age: 25};
    
    const copie = {...original};
    
    copie.age = 30;
    
    console.log(original.age);  // 25 (inchangé)
    console.log(copie.age);     // 30

    Fusionner des objets

    const infosBase = {nom: "Marie", age: 25};
    const infosContact = {email: "marie@example.com", tel: "0123"};
    
    const utilisateur = {...infosBase, ...infosContact};
    
    console.log(utilisateur);
    // {nom: "Marie", age: 25, email: "marie@example.com", tel: "0123"}

    Ajouter/Modifier des propriétés

    const user = {nom: "Marie", age: 25, ville: "Paris"};
    
    // Modifier une propriété
    const userModifie = {...user, age: 26};
    
    console.log(userModifie);
    // {nom: "Marie", age: 26, ville: "Paris"}
    
    // Ajouter de nouvelles propriétés
    const userComplet = {...user, email: "marie@example.com", role: "admin"};
    
    console.log(userComplet);
    // {nom: "Marie", age: 25, ville: "Paris", email: "marie@example.com", role: "admin"}

    Cas d'usage du spread 💡

    1. État immutable (React, Redux...)

    // Mettre à jour un objet sans le modifier
    const state = {
        user: {nom: "Marie", age: 25},
        isLogged: true
    };
    
    // ❌ Mauvais : modification directe
    state.user.age = 26;
    
    // ✅ Bon : créer un nouvel objet
    const newState = {
        ...state,
        user: {...state.user, age: 26}
    };

    2. Configuration par défaut

    const defaultConfig = {
        theme: "light",
        language: "fr",
        notifications: true
    };
    
    function creerConfig(userConfig) {
        return {...defaultConfig, ...userConfig};
    }
    
    const config = creerConfig({theme: "dark"});
    console.log(config);
    // {theme: "dark", language: "fr", notifications: true}

    3. Ajouter un élément dans un tableau immutable

    const todos = ["Faire les courses", "Apprendre JS"];
    
    const newTodos = [...todos, "Faire du sport"];
    
    console.log(newTodos);
    // ["Faire les courses", "Apprendre JS", "Faire du sport"]
    # 📄 Partie 5

    JSON

    JavaScript Object Notation

    C'est quoi JSON ? 📄

    JSON (JavaScript Object Notation) est un format de texte pour échanger des données.

    Analogie : Le colis postal 📦

    Quand tu envoies un colis, tu ne peux pas envoyer un objet "vivant" tel quel. Tu dois le emballer (stringify) dans une boîte. Le destinataire déballe (parse) le colis pour récupérer l'objet.

    JSON, c'est pareil : on transforme un objet JavaScript en texte pour l'envoyer, puis on le retransforme en objet.

    Objet JavaScript

    const user = {
        nom: "Marie",
        age: 25
    };

    En mémoire, utilisable en JS

    JSON (texte)

    '{"nom":"Marie","age":25}'

    Chaîne de caractères, transportable

    JSON.stringify : Objet → Texte 📤

    JSON.stringify() transforme un objet JavaScript en chaîne JSON.

    // Objet JavaScript
    const utilisateur = {
        nom: "Dupont",
        prenom: "Marie",
        age: 25,
        ville: "Paris"
    };
    
    // Convertir en JSON (texte)
    const json = JSON.stringify(utilisateur);
    
    console.log(json);
    // '{"nom":"Dupont","prenom":"Marie","age":25,"ville":"Paris"}'
    
    console.log(typeof json);  // "string" ← C'est du texte !

    Avec tableau

    const fruits = ["pomme", "banane", "orange"];
    
    const jsonFruits = JSON.stringify(fruits);
    
    console.log(jsonFruits);  // '["pomme","banane","orange"]'

    Formatage lisible (pretty print)

    const user = {nom: "Marie", age: 25, ville: "Paris"};
    
    // Sans formatage
    console.log(JSON.stringify(user));
    // '{"nom":"Marie","age":25,"ville":"Paris"}'
    
    // Avec indentation (2 espaces)
    console.log(JSON.stringify(user, null, 2));
    // {
    //   "nom": "Marie",
    //   "age": 25,
    //   "ville": "Paris"
    // }

    JSON.parse : Texte → Objet 📥

    JSON.parse() transforme une chaîne JSON en objet JavaScript.

    // Chaîne JSON (reçue d'une API par exemple)
    const jsonText = '{"nom":"Dupont","prenom":"Marie","age":25}';
    
    // Convertir en objet JavaScript
    const utilisateur = JSON.parse(jsonText);
    
    console.log(utilisateur);
    // {nom: "Dupont", prenom: "Marie", age: 25}
    
    console.log(typeof utilisateur);  // "object"
    
    // Maintenant on peut utiliser l'objet
    console.log(utilisateur.nom);     // "Dupont"
    console.log(utilisateur.age);     // 25

    Avec tableau

    const jsonArray = '["pomme","banane","orange"]';
    
    const fruits = JSON.parse(jsonArray);
    
    console.log(fruits);        // ["pomme", "banane", "orange"]
    console.log(fruits[0]);     // "pomme"
    console.log(Array.isArray(fruits));  // true

    ⚠️ Erreur de syntaxe JSON

    // JSON invalide
    const mauvaisJSON = "{nom: 'Marie'}";  // ❌ Guillemets simples
    
    try {
        JSON.parse(mauvaisJSON);
    } catch (error) {
        console.log("Erreur:", error.message);
        // Erreur: Unexpected token n in JSON...
    }

    JSON exige des guillemets doubles pour les clés ET les valeurs string !

    Règles du format JSON 📋

    ✅ Ce qui est accepté en JSON :

    ❌ Ce qui n'est PAS accepté en JSON :

    // ✅ JSON valide
    const bon = {
        "nom": "Marie",
        "age": 25,
        "actif": true,
        "hobbies": ["lecture", "sport"],
        "adresse": null
    };
    
    // ❌ Ces propriétés seront ignorées par stringify
    const mauvais = {
        nom: "Marie",
        dire: function() { },     // Fonction → ignorée
        inconnu: undefined,       // undefined → ignorée
        date: new Date()          // Date → convertie en string
    };

    Cas d'usage : localStorage 💾

    Le localStorage ne stocke que du texte. On utilise JSON pour sauvegarder des objets !

    // Sauvegarder un objet dans localStorage
    const user = {
        nom: "Marie",
        age: 25,
        preferences: {
            theme: "dark",
            lang: "fr"
        }
    };
    
    // Convertir en JSON avant de sauvegarder
    localStorage.setItem("user", JSON.stringify(user));
    
    // Récupérer et reconvertir en objet
    const userRecupere = JSON.parse(localStorage.getItem("user"));
    
    console.log(userRecupere.nom);  // "Marie"
    console.log(userRecupere.preferences.theme);  // "dark"

    Fonction helper

    // Sauvegarder facilement
    function sauvegarder(cle, valeur) {
        localStorage.setItem(cle, JSON.stringify(valeur));
    }
    
    // Récupérer facilement
    function recuperer(cle) {
        const data = localStorage.getItem(cle);
        return data ? JSON.parse(data) : null;
    }
    
    // Utilisation
    sauvegarder("config", {theme: "dark", lang: "fr"});
    const config = recuperer("config");
    console.log(config.theme);  // "dark"
    # 💡 Partie 6

    Exemples Complets

    Tout mettre en pratique

    Exemple 1 : Gestion de panier 🛒

    const produits = [
        {id: 1, nom: "PC", prix: 800, qte: 1},
        {id: 2, nom: "Souris", prix: 20, qte: 2},
        {id: 3, nom: "Écran", prix: 300, qte: 1}
    ];
    
    // 1. Calculer le total avec reduce
    const total = produits.reduce((acc, p) => acc + (p.prix * p.qte), 0);
    console.log(`Total: ${total}€`);  // Total: 1140€
    
    // 2. Ajouter la TVA (20%) avec map
    const avecTVA = produits.map(p => ({
        ...p,
        prixTTC: p.prix * 1.20
    }));
    
    console.log(avecTVA);
    // Chaque produit a maintenant prixTTC
    
    // 3. Filtrer les produits chers (> 50€)
    const chers = produits.filter(p => p.prix > 50);
    
    console.log(chers.map(p => p.nom));  // ["PC", "Écran"]
    
    // 4. Destructuration pour affichage
    avecTVA.forEach(({nom, prix, prixTTC, qte}) => {
        console.log(`${nom}: ${prix}€ HT → ${prixTTC}€ TTC (x${qte})`);
    });
    
    // 5. Sauvegarder dans localStorage
    localStorage.setItem("panier", JSON.stringify(produits));
    
    // 6. Récupérer plus tard
    const panierSauvegarde = JSON.parse(localStorage.getItem("panier"));
    console.log(panierSauvegarde);

    Exemple 2 : Traitement de données utilisateurs 👥

    const utilisateurs = [
        {id: 1, nom: "Dupont", prenom: "Marie", age: 25, ville: "Paris"},
        {id: 2, nom: "Martin", prenom: "Jean", age: 17, ville: "Lyon"},
        {id: 3, nom: "Durand", prenom: "Sophie", age: 30, ville: "Paris"},
        {id: 4, nom: "Bernard", prenom: "Luc", age: 22, ville: "Marseille"}
    ];
    
    // 1. Extraire tous les noms complets
    const noms = utilisateurs.map(({nom, prenom}) => `${prenom} ${nom}`);
    console.log(noms);
    // ["Marie Dupont", "Jean Martin", "Sophie Durand", "Luc Bernard"]
    
    // 2. Filtrer les majeurs à Paris
    const majeursAParis = utilisateurs
        .filter(u => u.age >= 18)
        .filter(u => u.ville === "Paris");
    
    console.log(majeursAParis);
    // [{id: 1, ...}, {id: 3, ...}]
    
    // 3. Calculer l'âge moyen
    const ageMoyen = utilisateurs.reduce((acc, u) => acc + u.age, 0) 
                                  / utilisateurs.length;
    console.log(`Âge moyen: ${ageMoyen}`);  // 23.5
    
    // 4. Grouper par ville
    const parVille = utilisateurs.reduce((acc, user) => {
        const {ville} = user;
        if (!acc[ville]) {
            acc[ville] = [];
        }
        acc[ville].push(user);
        return acc;
    }, {});
    
    console.log(parVille);
    // {
    //   Paris: [{...}, {...}],
    //   Lyon: [{...}],
    //   Marseille: [{...}]
    // }
    
    // 5. Exporter en JSON pour une API
    const json = JSON.stringify(utilisateurs, null, 2);
    console.log(json);

    Exemple 3 : Configuration et merge 🔧

    // Configuration par défaut
    const defaultConfig = {
        theme: "light",
        language: "fr",
        notifications: {
            email: true,
            push: false,
            sms: false
        },
        display: {
            fontSize: 14,
            compactMode: false
        }
    };
    
    // Configuration utilisateur (partielle)
    const userConfig = {
        theme: "dark",
        notifications: {
            push: true
        }
    };
    
    // Merge superficiel (écrase tout l'objet notifications)
    const config1 = {...defaultConfig, ...userConfig};
    console.log(config1.notifications);
    // {push: true} ← email et sms ont disparu ! ❌
    
    // Merge profond (correct)
    const config2 = {
        ...defaultConfig,
        ...userConfig,
        notifications: {
            ...defaultConfig.notifications,
            ...userConfig.notifications
        }
    };
    
    console.log(config2.notifications);
    // {email: true, push: true, sms: false} ✅
    
    // Fonction helper pour merge profond simple
    function mergeConfig(defaults, user) {
        const result = {...defaults};
        
        for (let [key, value] of Object.entries(user)) {
            if (typeof value === 'object' && !Array.isArray(value)) {
                result[key] = {...defaults[key], ...value};
            } else {
                result[key] = value;
            }
        }
        
        return result;
    }
    
    const finalConfig = mergeConfig(defaultConfig, userConfig);
    console.log(finalConfig);
    # 🎓 Récapitulatif

    Ce qu'on a appris

    Résumé complet 📚

    Concept Syntaxe Usage
    map arr.map(x => ...) Transformer chaque élément
    filter arr.filter(x => ...) Garder certains éléments
    reduce arr.reduce((a,x) => ..., init) Réduire à une valeur
    Destructuration [] const [a, b] = arr Extraire d'un tableau
    Destructuration {} const {x, y} = obj Extraire d'un objet
    Spread array [...arr] Copier/combiner tableaux
    Spread object {...obj} Copier/fusionner objets
    JSON.stringify JSON.stringify(obj) Objet → texte
    JSON.parse JSON.parse(text) Texte → objet

    Bonnes pratiques 💡

    1. Préfère les méthodes de tableaux aux boucles
      Plus lisible et moins d'erreurs
    2. Utilise la destructuration
      Rend le code plus concis et clair
    3. Copie avec spread plutôt que Object.assign
      Syntaxe plus moderne et lisible
    4. Chaîne les méthodes intelligemment
      Mais pas trop : reste lisible
    5. Utilise JSON pour le stockage
      localStorage, API, fichiers...
    6. Attention aux mutations
      Préfère créer de nouveaux objets/tableaux

    🎓 Fin du cours

    Structures de Données JavaScript

    Vous maîtrisez maintenant :

    🗺️ Les méthodes de tableaux (map, filter, reduce...)

    🎯 La manipulation d'objets

    📤 La destructuration

    ✨ Le spread operator

    📄 JSON (parse et stringify)

    Pratiquez avec des exemples réels ! 💪

    Formation DWWM - 2026