Cours JavaScript et TypeScript · Module 2: Fonctions, tableaux et objets
La déstructuration des objets et des tableaux
Dans cette leçon8
Un rapport du laboratoire de Jurassic Park est un objet rempli de données : constantes vitales, coordonnées GPS, résultats d'analyses ADN. Pour en faire quelque chose, tu dois extraire les valeurs une par une : report.vitals.heartRate, report.location.zone et ainsi de suite, en recommençant à chaque fois. "La déstructuration, c'est comme trier des échantillons d'ADN", dit le Dr Rex. "Au lieu de sortir chaque éprouvette à la main, tu prends d'un seul geste exactement les données dont tu as besoin."
La déstructuration d'objets - les bases
La déstructuration d'un objet extrait ses propriétés dans des variables séparées, en une seule ligne. Compare les deux écritures :
1const dinosaur = {
2 name: 'Rex',
3 species: 'Tyrannosaurus',
4 weight: 8000,
5 zone: 'A'
6};
7
8// Sans déstructuration
9const name1 = dinosaur.name;
10const weight1 = dinosaur.weight;
11
12// Avec déstructuration - bien plus court !
13const { name, species, weight, zone } = dinosaur;
14console.log(name); // "Rex"
15console.log(species); // "Tyrannosaurus"
16console.log(weight); // 8000Les accolades à gauche du signe = ne créent pas de nouvel objet. C'est un motif qui dit : "crée des variables portant ces noms et mets-y les valeurs des propriétés du même nom". L'objet dinosaur reste intact, rien n'en disparaît et rien ne s'y ajoute.
Renommer une variable (alias)
Parfois, le nom d'une propriété entre en conflit avec une variable existante, ou il est simplement peu lisible. Tu indiques alors un nouveau nom après les deux-points. Tu n'es pas non plus obligé d'extraire toutes les propriétés, seulement celles dont tu as besoin :
1const { name: dinoName, zone: dinoZone } = dinosaur;
2console.log(dinoName); // "Rex"
3console.log(dinoZone); // "A"Seules les variables dinoName et dinoZone ont été créées. Les variables name et zone ne sont pas créées par cette écriture, car le nom avant les deux-points indique seulement quelle propriété on lit. On peut utiliser plusieurs alias à la fois :
1const sensor = { id: 'S-001', value: 42.5, status: 'active' };
2
3// On renomme les variables
4const { id: sensorId, value: reading, status: sensorStatus } = sensor;
5console.log(sensorId); // "S-001"
6console.log(reading); // 42.5
7console.log(sensorStatus); // "active"Lis les deux-points comme "enregistre dans" : id: sensorId signifie "prends id et enregistre-le dans sensorId".
Les valeurs par défaut
Si une propriété manque dans l'objet, tu peux définir une valeur par défaut après le signe =. L'alias et la valeur par défaut se combinent dans une même écriture :
1const specimen = { name: 'Blue', species: 'Velociraptor' };
2
3// health n'existe pas dans l'objet - on utilise la valeur par défaut
4const { name: specimenName, health = 100, zone: specimenZone = 'Inconnue' } = specimen;
5console.log(specimenName); // "Blue"
6console.log(health); // 100 (par défaut)
7console.log(specimenZone); // "Inconnue" (par défaut)La valeur par défaut ne s'applique que si la propriété manque ou vaut undefined. Si l'objet avait health: 95, tu obtiendrais 95, et avec health: null tu obtiendrais null, car null est une valeur écrite volontairement.
La déstructuration imbriquée
Les objets contiennent souvent des structures imbriquées, et la déstructuration permet d'aller en profondeur en reproduisant la forme de l'objet :
1const dinoReport = {
2 name: 'Rex',
3 vitals: {
4 heartRate: 65,
5 temperature: 37.2,
6 bloodPressure: { systolic: 120, diastolic: 80 }
7 },
8 location: { zone: 'A', sector: 3 }
9};
10
11// Déstructuration imbriquée
12const {
13 name: reportName,
14 vitals: { heartRate, temperature },
15 location: { zone: reportZone, sector }
16} = dinoReport;
17
18console.log(reportName); // "Rex"
19console.log(heartRate); // 65
20console.log(temperature); // 37.2
21console.log(reportZone); // "A"
22console.log(sector); // 3Attention à une erreur fréquente : l'écriture vitals: { heartRate } ne crée pas de variable vitals, elle indique seulement le chemin vers heartRate. Si vitals manquait dans le rapport, tu obtiendrais un TypeError. C'est pourquoi je te recommande de descendre de deux niveaux au maximum, car les motifs plus profonds sont difficiles à lire.
La déstructuration de tableaux
On déstructure les tableaux entre crochets. Ici, c'est la position qui compte, pas le nom, tu peux donc nommer les variables comme tu veux :
1const dnaSequence = ['A', 'T', 'C', 'G', 'T', 'A'];
2
3// On extrait les trois premiers éléments
4const [first, second, third] = dnaSequence;
5console.log(first); // "A"
6console.log(second); // "T"
7console.log(third); // "C"
8
9// Sauter des éléments à l'aide de virgules
10const [, , thirdNucleotide, , fifthNucleotide] = dnaSequence;
11console.log(thirdNucleotide); // "C"
12console.log(fifthNucleotide); // "T"Chaque virgule vide saute une position. Dans l'écriture const [a, , b] = ['Rex', 'Blue', 'Delta'], la variable a reçoit 'Rex', 'Blue' est ignoré, et b reçoit 'Delta'.
Échanger les valeurs de variables
La déstructuration de tableaux permet d'échanger élégamment les valeurs de deux variables sans variable temporaire, par exemple quand deux dinosaures échangent leurs enclos :
1let zoneA = 'Rex';
2let zoneB = 'Blue';
3
4// Échange des valeurs
5[zoneA, zoneB] = [zoneB, zoneA];
6console.log(zoneA); // "Blue"
7console.log(zoneB); // "Rex"Le côté droit crée un tableau temporaire ['Blue', 'Rex'], et le côté gauche le décompose aussitôt. Veille au point-virgule sur la ligne précédente : une ligne qui commence par [ sans lui se collera à la précédente, et l'échange se terminera par une erreur.
Les valeurs par défaut dans les tableaux
Les tableaux acceptent aussi des valeurs par défaut. Quand le capteur GPS n'a envoyé qu'une seule coordonnée, la seconde reçoit une valeur de secours :
1const coordinates = [12.5];
2const [latitude, longitude = 0] = coordinates;
3console.log(latitude); // 12.5
4console.log(longitude); // 0 (par défaut)La position 1 n'existe pas dans le tableau, donc longitude reçoit 0 au lieu de undefined.
La déstructuration dans les paramètres de fonction
La déstructuration est particulièrement utile dans les paramètres de fonction. La fonction reçoit un objet et en choisit aussitôt les champs nécessaires :
1// Déstructuration d'objet dans un paramètre
2function displayDino({ name, species, weight = 'inconnu' }) {
3 console.log(`${name} (${species}) - ${weight} kg`);
4}
5
6displayDino({ name: 'Rex', species: 'T-Rex', weight: 8000 });
7// "Rex (T-Rex) - 8000 kg"
8
9displayDino({ name: 'Blue', species: 'Velociraptor' });
10// "Blue (Velociraptor) - inconnu kg"
11
12// Déstructuration de tableau dans un paramètre
13function processCoords([lat, lon]) {
14 console.log(`Latitude : ${lat}, Longitude : ${lon}`);
15}
16
17processCoords([12.345, 67.890]);
18// "Latitude : 12.345, Longitude : 67.89"L'ordre des champs dans l'objet transmis n'a pas d'importance, et l'appel décrit à lui seul ce qui est quoi. C'est pourquoi je te recommande cette écriture dès qu'une fonction a plus de deux paramètres. Remarque aussi que le nombre 67.890 s'affiche 67.89, car la conversion d'un nombre en texte omet les zéros finaux. L'appel displayDino() sans argument lèvera un TypeError, donc quand l'objet est facultatif, ajoute la valeur par défaut = {} après le motif.
Combiner la déstructuration avec le reste (rest)
L'opérateur ... rassemble le "reste" des éléments dans un nouveau tableau ou un nouvel objet :
1const allSpecies = ['T-Rex', 'Velociraptor', 'Triceratops', 'Brachio', 'Stego'];
2
3const [firstSpecies, secondSpecies, ...otherSpecies] = allSpecies;
4console.log(firstSpecies); // "T-Rex"
5console.log(secondSpecies); // "Velociraptor"
6console.log(otherSpecies); // ["Triceratops", "Brachio", "Stego"]
7
8// Rest dans les objets
9const fullDino = { name: 'Rex', species: 'T-Rex', weight: 8000, zone: 'A', health: 95 };
10const { name: restName, ...dinoStats } = fullDino;
11console.log(restName); // "Rex"
12console.log(dinoStats); // { species: "T-Rex", weight: 8000, zone: "A", health: 95 }Le rest doit se trouver à la fin du motif, et fullDino a toujours ses cinq propriétés. Dans la prochaine leçon, tu verras que ces mêmes trois points savent aussi décompresser des données.
Pratique
Dans le bac à sable t'attendent la déstructuration d'un objet, les alias avec valeurs par défaut et le rapport imbriqué. Ajoute tes propres motifs et vérifie dans la console quelles variables ont été créées.
Code de cette leçon : index.js
1// === DÉSTRUCTURATION D'OBJETS ET DE TABLEAUX ===
2
3// 1. Déstructuration d'objet
4const dinosaur = { name: 'Rex', species: 'Tyrannosaurus', weight: 8000, zone: 'A' };
5const { name, species, weight } = dinosaur;
6console.log('=== Objet ===');
7console.log('Nom:', name, '| Espèce:', species, '| Poids:', weight);
8
9// 2. Changement de nom (alias) et valeurs par défaut
10const sensor = { id: 'S-001', value: 42.5 };
11const { id: sensorId, value: reading, status: sensorStatus = 'actif' } = sensor;
12console.log('\n=== Alias et valeurs par défaut ===');
13console.log('ID:', sensorId, '| Lecture:', reading, '| Statut:', sensorStatus);
14
15// 3. Déstructuration imbriquée
16const report = {
17 name: 'Rex',
18 vitals: { heartRate: 65, temperature: 37.2 },
19 location: { zone: 'A', sector: 3 }
20};
21const { vitals: { heartRate, temperature }, location: { zone } } = report;
22console.log('\n=== Imbriquée ===');
23console.log('Pouls:', heartRate, '| Temp:', temperature, '| Zone:', zone);
24
25// 4. Déstructuration de tableau
26const dna = ['A', 'T', 'C', 'G', 'T', 'A'];
27const [first, second, third] = dna;
28console.log('\n=== Tableau ===');
29console.log('Premiers 3:', first, second, third);
30
31// Omission d'éléments
32const [, , thirdEl, , fifthEl] = dna;
33console.log('Troisième:', thirdEl, '| Cinquième:', fifthEl);
34
35// 5. Échange de valeurs
36let zoneA = 'Rex';
37let zoneB = 'Blue';
38[zoneA, zoneB] = [zoneB, zoneA];
39console.log('\n=== Échange ===');
40console.log('zoneA:', zoneA, '| zoneB:', zoneB);
41
42// 6. Déstructuration dans les paramètres de fonction
43function displayDino({ name: n, species: s, weight: w = 'inconnu' }) {
44 console.log(n + ' (' + s + ') - ' + w + ' kg');
45}
46console.log('\n=== Paramètres de fonction ===');
47displayDino({ name: 'Rex', species: 'T-Rex', weight: 8000 });
48displayDino({ name: 'Blue', species: 'Velociraptor' });
49
50// 7. Rest dans la déstructuration
51const all = { name: 'Rex', species: 'T-Rex', weight: 8000, zone: 'A', health: 95 };
52const { name: dName, ...stats } = all;
53console.log('\n=== Rest ===');
54console.log('Nom:', dName);
55console.log('Reste:', JSON.stringify(stats));Retiens bien : la déstructuration est une salle de tri des échantillons, qui déplace d'un seul geste les éprouvettes nécessaires sur la table et laisse le rapport d'origine intact.
Tu as repéré une erreur dans cette leçon ?
Teste tes connaissances
Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.
1. Que fait l'expression const { name, weight } = dinosaur ?
2. Que signifie l'expression const { id: sensorId, status = 'active' } = sensor ?
3. Comment échanger les valeurs de deux variables à l'aide de la déstructuration de tableau ?
Tâches pratiques dans le jeu
- Éditeur de code
Tu as un objet const dino = { name: 'Rex', species: 'T-Rex', stats: { weight: 8000, speed: 30 } } et un tableau const zones = ['A', 'B', 'C', 'D']. Avec la déstructuration d'objet, crée les variables dinoName (alias de name), species, weight (dans l'objet imbriqué stats) et diet avec la valeur par défaut 'carnivore'. Avec la déstructuration de tableau, crée firstZone, secondZone et otherZones avec les éléments restants. Écris aussi une fonction describeDino({ name, species }) qui déstructure son paramètre et renvoie le texte name + ' (' + species + ')'.
- Tri vertical
Range ce qui sera assigné aux variables dans la déstructuration const [a, , b] = ['Rex', 'Blue', 'Delta'] :
- Clique dans l'ordre
Range les éléments de la déstructuration imbriquée : const { vitals: { heartRate } } = report
- Éditeur de code
Tu as un rapport : const report = { id: 'R-7', dino: { name: 'Blue', vitals: { heartRate: 65, temperature: 37.2 } }, zone: 'B', status: 'ok' }. Avec la déstructuration, crée : id, patientName (alias de report.dino.name), heartRate (dans report.dino.vitals) et un objet meta qui rassemble avec l'opérateur rest les autres propriétés de premier niveau (sans id ni dino). Écris aussi une fonction formatVitals({ heartRate, temperature = 36.6 }) qui renvoie le texte heartRate + ' bpm, ' + temperature + ' C'.