- Apprendre
- Informatique et numérique
- Programmation
- JavaScript : DOM, événements et code asynchrone
- Objets JavaScript et JSON
Objets JavaScript et JSON : modéliser des données
DébutantUnité 4 sur 9 de la formation Formation : JavaScript : DOM, événements et code asynchrone
Ce que tu vas apprendre
- Décris des éléments réels dans le code sous forme d’objets aux propriétés nommées, lis et modifie ces propriétés, et comprends comment les objets sont stockés, copiés et comparés.
- Crée des objets et manipule leurs propriétésÉcris des littéraux d’objet, lis des propriétés avec la notation pointée et la notation entre crochets, et ajoute, modifie et supprime des propriétés.
- Vérifie les propriétés d’un objet et parcours-les avec une boucleTeste l’existence d’une propriété, liste les clés, les valeurs et les entrées, et parcours ou transforme les propriétés d’un objet.
- Comprends les références, la copie et la comparaisonExplique pourquoi les objets sont partagés par référence, compare correctement les objets et crée des copies superficielles et profondes.
- Manipule des données imbriquéesLis et traite des objets à l’intérieur d’objets et des tableaux d’objets, protège-toi contre les éléments absents avec ?. et ??, et choisis une structure adaptée aux données.
- Crée des objets et manipule leurs propriétés
- Écris des méthodes qui utilisent les données de leur objet, explique comment la valeur du mot-clé this est déterminée selon la façon dont une fonction est appelée, et conserve la bonne valeur de this lorsqu’une méthode est transmise.
- Écris des méthodes qui utilisent les données de leur objetDéfinis des méthodes avec la notation abrégée, utilise this pour lire et mettre à jour l’objet, et appelle correctement les méthodes.
- Explique comment la valeur de this est déterminéeDétermine la valeur de this selon la façon dont une fonction est appelée et explique pourquoi les fonctions fléchées se comportent différemment.
- Conserve la valeur de this lorsque tu passes des méthodes comme fonctions de rappelRepère lorsqu’une méthode perd son objet et corrige le problème avec une fonction fléchée enveloppante, bind, call ou apply.
- Écris des méthodes qui utilisent les données de leur objet
- Extrais des valeurs d’objets et de tableaux avec la déstructuration, et copie, fusionne et regroupe des valeurs avec la syntaxe de décomposition et du reste.
- Déstructure des objetsExtrais les propriétés d’un objet dans des variables, avec renommage, valeurs par défaut, motifs imbriqués et paramètres de fonction déstructurés.
- Déstructure des tableaux et d’autres itérablesExtrais des valeurs selon leur position, ignore certaines valeurs et définis des valeurs par défaut, échange des variables et déstructure des entrées dans des boucles.
- Copie, fusionne et regroupe des données avec la décomposition et le resteUtilise la décomposition pour copier et fusionner des objets et des tableaux et pour passer les éléments d’un tableau comme arguments, utilise le reste pour regrouper des valeurs et distingue les deux.
- Déstructure des objets
- Utilise Map pour des collections de paires clé-valeur dont les clés peuvent être de tout type et Set pour des collections de valeurs uniques, et choisis entre ces structures, les objets simples et les tableaux.
- Stocke des paires clé-valeur dans une MapCrée et mets à jour une Map, parcours ses entrées, convertis des Map en objets et inversement, et détermine quand une Map convient mieux qu’un objet.
- Conserve des valeurs uniques dans un SetCrée et mets à jour un Set, supprime les doublons de tableaux et compare des collections avec des opérations ensemblistes.
- Stocke des paires clé-valeur dans une Map
- Lis et écris le format texte JSON, convertis des valeurs JavaScript en JSON avec JSON.stringify et du texte JSON en valeurs avec JSON.parse, et traite les cas où les deux ne correspondent pas.
- Lis et écris au format JSONReconnais du JSON valide, explique en quoi il diffère d’un littéral d’objet JavaScript et repère les erreurs de syntaxe courantes.
- Convertis des valeurs en texte JSON avec JSON.stringifyConvertis des objets et des tableaux en chaînes JSON, mets le résultat en forme, choisis les propriétés à inclure et prévois ce qui est omis ou modifié.
- Convertis du texte JSON en valeurs avec JSON.parseAnalyse du JSON de manière sûre, restaure des valeurs comme les dates avec une fonction de rappel reviver, vérifie les données analysées et effectue des allers-retours de données par JSON.
- Lis et écris au format JSON
Objets JavaScript et JSON : cours
1Modélise des données avec des objets
Un objet rassemble des valeurs liées sous des noms, ce qui permet à un enregistrement de décrire un livre, une personne ou un relevé. En manipulant ces noms, tu peux modifier un champ, examiner un enregistrement entier et organiser des listes d’enregistrements. Tu suivras aussi les variables qui pointent vers un même objet. Cette distinction compte lorsqu’une modification apparaît à deux endroits, qu’une copie contient des données imbriquées ou qu’un champ absent nécessite une valeur par défaut adaptée.
1.1 Crée des objets et manipule leurs propriétés
Un objet regroupe des valeurs liées sous des noms. Chaque propriété associe une clé à une valeur. Utilise un objet pour un enregistrement et un tableau d’objets pour une liste ordonnée. Des tableaux parallèles peuvent perdre leur correspondance lorsqu’un seul est trié ou modifié.
Créer et lire un enregistrement
const book = { title: "Dune", pages: 412, available: true };
book.title; // "Dune"
book["title"]; // "Dune"
Les valeurs des propriétés peuvent être des tableaux, des objets ou des fonctions, ainsi que des valeurs primitives. Les clés sont des chaînes de caractères ou des symboles ; ces exemples utilisent des chaînes. Les clés qui sont des chaînes et des identifiants valides n’ont pas besoin de guillemets. Les clés contenant des espaces ou des traits d’union en ont besoin : { "release-year": 1965 }. Les clés numériques deviennent des chaînes de caractères : { 1: "a" } possède donc la clé "1". Les littéraux d’objet autorisent une virgule finale.
L’accès par notation pointée utilise le nom littéral après le point. L’accès entre crochets évalue une expression :
const field = "pages";
book[field]; // 412
book.field; // undefined
La seconde expression cherche une propriété nommée "field". Les crochets permettent aussi d’utiliser book["release-year"]. Une propriété absente renvoie undefined ; poursuivre l’accès à travers elle, comme dans book.author.name, lève une TypeError lorsque la propriété author est absente.
Modifier le contenu de l’objet
book.author = "Frank Herbert";
book.pages = 896;
delete book.available;
L’affectation ajoute une propriété absente ou remplace une valeur existante. La suppression retire la propriété elle-même : "available" in book est donc désormais faux. const maintient la variable liée à cet objet, mais permet de modifier son contenu.
Pour const reading = { city: "Nairobi", tempC: 24.5 };, reading.tempC += 1.5; stocke 26. Puis reading.humidity = 61; ajoute un champ. Avec const key = "humidity";, reading[key] lit 61. Un nom comme tempC rend l’unité de mesure visible.
Utiliser des variables dans un littéral
const name = "Lena";
const age = 29;
const person = { name, age };
const lang = "nl";
const greeting = { [lang]: "Hallo" };
La notation abrégée { name, age } signifie { name: name, age: age }. Un nom calculé évalue l’expression entre crochets : greeting possède la propriété "nl". Sans ces crochets, { lang: "Hallo" } créerait la clé littérale "lang".
Points clés
- Un objet regroupe des valeurs liées dans des propriétés nommées.
- Utilise les crochets pour une clé stockée dans une variable ou contenant un trait d’union.
- L’affectation ajoute ou remplace une propriété ;
deletela supprime. constfixe la variable, pas le contenu de l’objet.- La notation abrégée prend la valeur d’une variable ; une clé calculée évalue une expression.
1.2 Vérifie les propriétés d’un objet et parcours-les avec une boucle
Vérifier si un champ existe est différent de vérifier sa valeur. Une chaîne vide, zéro ou false peut être une valeur stockée parfaitement valide.
Poser la bonne question sur l’existence
const item = { stock: 0, note: undefined };
Object.hasOwn(item, "stock"); // true
"note" in item; // true
Boolean(item.stock); // false
Object.hasOwn(obj, key) vérifie uniquement les propriétés propres de l’objet. L’opérateur in vérifie aussi les propriétés héritées : "toString" in {} vaut true, tandis que Object.hasOwn({}, "toString") vaut false. Le code plus ancien appelle souvent obj.hasOwnProperty(key).
Une condition comme if (item.stock) teste si la valeur est vraie. Elle ne peut pas distinguer un champ absent d’un champ présent qui contient zéro. Le même problème se pose pour "", false, null, undefined et NaN. Même une valeur undefined peut appartenir à une propriété existante, comme c’est le cas de note ci-dessus.
Choisir les clés, les valeurs ou les paires
Pour const scores = { Ana: 82, Ben: 74, Chen: 91 };, ces fonctions renvoient des tableaux à partir des propriétés propres énumérables dont les clés sont des chaînes de caractères :
| Expression | Résultat |
|---|---|
Object.keys(scores) | ["Ana", "Ben", "Chen"] |
Object.values(scores) | [82, 74, 91] |
Object.entries(scores) | [["Ana", 82], ["Ben", 74], ["Chen", 91]] |
L’objet n’a pas de longueur comme un tableau : scores.length vaut undefined. Object.keys(scores).length compte trois propriétés. Pour calculer le total des scores, réduis les valeurs en partant de zéro. Leur somme est de 247 et leur moyenne d’environ 82,33.
Parcourir les deux parties à la fois
let bestName;
let bestScore = -Infinity;
for (const [name, score] of Object.entries(scores)) {
if (score > bestScore) {
bestName = name;
bestScore = score;
}
}
La boucle compare 82, 74, puis 91 au meilleur score rencontré jusque-là. Elle se termine avec "Chen" et 91. Le motif entre crochets donne des noms aux deux parties de chaque paire.
Un objet simple n’est pas itérable : for...of scores lève donc une TypeError. Object.entries(scores) fournit un tableau itérable. La boucle plus ancienne for...in produit des clés qui sont des chaînes de caractères et peut inclure des propriétés énumérables héritées.
Transformer les entrées en objet
const weightsG = { flour: 500, sugar: 250, salt: 5 };
const weightsKg = Object.fromEntries(
Object.entries(weightsG).map(([item, g]) => [item, g / 1000])
);
entries produit des paires, map modifie chaque valeur tout en conservant sa clé, et fromEntries reconstruit l’enregistrement. Le résultat est { flour: 0.5, sugar: 0.25, salt: 0.005 } ; weightsG reste inchangé.
L’ordre des propriétés propres est défini. Les clés d’indice de tableau de "0" à "4294967294" apparaissent d’abord par ordre croissant ; les autres clés qui sont des chaînes suivent dans leur ordre d’insertion. Un zéro initial, comme dans "01", empêche une clé d’être un indice de tableau. Ainsi, Object.keys({ b: 1, 2: "x", a: 2, 1: "y" }) donne ["1", "2", "b", "a"]. Utilise un tableau lorsque les positions ont un sens.
Points clés
- L’existence d’une propriété et le fait que sa valeur soit vraie répondent à des questions différentes.
Object.hasOwnvérifie les propriétés propres ;invérifie aussi les propriétés héritées.Object.entriesfournit des paires clé-valeur pour les boucles et les transformations.Object.fromEntriesreconstruit un objet à partir de paires.- Dans l’ordre des propriétés, les clés d’indice de tableau précèdent les autres clés qui sont des chaînes de caractères.
- Compte les clés propres énumérables qui sont des chaînes de caractères avec
Object.keys(obj).length.
1.3 Comprends les références, la copie et la comparaison
Deux variables peuvent faire référence à un même objet. Avant de prévoir une mise à jour, détermine si le code a créé un nouvel objet ou copié une référence à un objet existant.
Distinguer l’identité des données
const p1 = { x: 1 };
const p2 = p1;
p2.x = 99;
p1.x; // 99
p1 === p2; // true
L’affectation a copié la référence. Les deux noms donnent accès à la même propriété. L’affectation d’une valeur primitive fonctionne différemment : après let a = 5; let b = a; b = 6;, a reste égal à 5.
Les objets sont comparés par identité avec === comme avec ==. Deux littéraux créent des objets distincts même lorsque tous leurs champs correspondent : ({ x: 1 } === { x: 1 }) vaut false. Pour comparer leurs données, compare les propriétés pertinentes. Une apparence identique à l’affichage ne vérifie pas l’identité.
Passer un objet à une fonction copie aussi sa référence. Une fonction qui exécute order.status = "shipped"; modifie l’objet de l’appelant. Renvoyer plutôt { ...order, status: "shipped" } crée un nouvel enregistrement au niveau supérieur.
Distinguer const, le gel et la copie
const cart = { items: 2 }; autorise cart.items = 3;, mais la réaffectation cart = {}; lève une TypeError. Object.freeze(cart) empêche de modifier les propriétés propres de l’objet. En mode strict, toute tentative de les ajouter, de les supprimer ou de remplacer leur valeur lève une TypeError.
Le gel est superficiel. Si un enregistrement gelé contient un autre objet, les champs de cet objet imbriqué peuvent encore changer. Un contenant gelé et une structure entièrement immuable sont deux choses différentes.
Suivre une copie superficielle
const settings = { theme: "dark", font: { size: 14 } };
const copy = { ...settings };
copy.theme = "light";
copy.font.size = 18;
La décomposition crée un nouvel objet extérieur. Sa valeur theme est copiée : modifier copy.theme laisse donc settings.theme à "dark". Sa valeur font est une référence copiée dans les deux enregistrements. Mettre à jour copy.font.size donne donc aussi la valeur 18 à settings.font.size.
Object.assign({}, settings) crée aussi une copie superficielle. Une copie superficielle sépare l’enregistrement extérieur tout en conservant l’identité des objets et tableaux imbriqués.
Copier les données imbriquées lorsqu’elles doivent être indépendantes
const deep = structuredClone(settings);
deep.font.size = 22;
settings.font.size; // 18
structuredClone copie les objets et tableaux imbriqués, ainsi que les valeurs prises en charge comme Map, Set et Date. Il prend aussi en charge les références circulaires. Le nouvel objet imbriqué font peut changer indépendamment. Les fonctions ne peuvent pas être clonées de cette façon : un objet contenant une méthode provoque une DataCloneError.
Un aller-retour par JSON, JSON.parse(JSON.stringify(obj)), copie uniquement les données compatibles avec JSON. Il omet les propriétés d’objet contenant undefined ou des fonctions, transforme les dates en chaînes de caractères et perd les entrées de Map et de Set sauf si tu les convertis. Choisis un clonage pour obtenir des données JavaScript indépendantes et prises en charge, et choisis JSON lorsque tu souhaites créer une représentation textuelle.
Points clés
- L’affectation et les appels de fonction copient les références aux objets.
- Les objets sont comparés par identité, même lorsque leurs champs correspondent.
- Une copie superficielle partage les objets imbriqués.
Object.freezeempêche de modifier les propriétés propres, mais son effet est superficiel.structuredClonecopie les données imbriquées prises en charge et rejette les fonctions.
1.4 Manipule des données imbriquées
Les données imbriquées combinent des enregistrements et des listes. Lis un chemin étape par étape, en vérifiant si chacune mène à un objet, à un tableau ou à une valeur finale.
Lire et traiter une liste dans un enregistrement
const order = {
id: 1042,
customer: { name: "Sara", city: "Lisbon" },
items: [
{ product: "Tea", qty: 2, unitPrice: 4.5 },
{ product: "Mug", qty: 1, unitPrice: 9 }
]
};
order.customer.city lit "Lisbon". order.items[1].product sélectionne d’abord le tableau des articles, puis son deuxième enregistrement, puis "Mug". order.items.length vaut 2.
Les méthodes de tableau que tu connais déjà fonctionnent avec les propriétés des enregistrements. map(item => item.product) produit les noms des produits. filter(item => item.qty > 1) conserve la ligne du thé. find(item => item.product === "Mug") renvoie l’enregistrement existant de la tasse : modifier l’enregistrement renvoyé modifie donc l’article dans la commande.
Pour calculer le total, utilise order.items.reduce((sum, item) => sum + item.qty * item.unitPrice, 0). La première ligne ajoute 9 ; la seconde ajoute encore 9, ce qui donne 18. Calculer le total au besoin évite qu’un total stocké séparément devienne périmé lorsque les articles changent.
Lire des données facultatives avec une solution de repli
order.shipping?.date; // undefined
order.customer?.city ?? "unknown"; // "Lisbon"
Le chaînage optionnel, ?., s’arrête lorsque la valeur immédiatement à sa gauche est null ou undefined. Un accès direct avec order.shipping.date lèverait une TypeError. Utilise une vérification à chaque maillon facultatif d’un chemin plus long. L’accès entre crochets et les appels le prennent aussi en charge : order.items?.[0] et order.print?.().
Le chaînage optionnel sert aux valeurs qui peuvent être absentes. Les champs obligatoires nécessitent toujours des vérifications ou des erreurs qui révèlent un enregistrement incorrect. Il ne peut pas apparaître à gauche d’une affectation : order.shipping?.date = "2026-05-01" est une erreur de syntaxe.
L’opérateur de coalescence des nuls, ??, n’utilise la valeur à sa droite que pour null ou undefined. Il préserve zéro, false et "". Pour const qty = 0;, qty ?? 1 reste égal à zéro, tandis que qty || 1 devient égal à 1 car || remplace toute valeur fausse.
Choisir une structure adaptée
Un tableau d’enregistrements convient pour lister, filtrer et ordonner des données. Un objet dont les clés sont des identifiants permet une recherche directe : usersById["u23"].name. Une Map est utile lorsque des clés de recherche sont fréquemment ajoutées et supprimées.
Les versions récentes de JavaScript proposent Object.groupBy, largement disponible depuis 2024 :
const tasks = [
{ title: "Book flights", status: "done" },
{ title: "Pack", status: "todo" },
{ title: "Renew passport", status: "done" }
];
const grouped = Object.groupBy(tasks, task => task.status);
grouped.done contient deux enregistrements et grouped.todo en contient un. Le résultat n’a pas de prototype et ne possède donc pas de méthode héritée toString. Une solution plus ancienne construit explicitement les tableaux pour ces clés d’état :
const groupedOlder = tasks.reduce((groups, task) => {
if (!Object.hasOwn(groups, task.status)) {
groups[task.status] = [];
}
groups[task.status].push(task);
return groups;
}, {});
Le premier enregistrement de chaque groupe crée son tableau. Les enregistrements suivants s’ajoutent à ce même tableau. Cet accumulateur est un objet ordinaire ; le résultat de la méthode plus récente n’a pas de prototype. Utilise des noms et des types de valeurs cohérents entre les enregistrements ; des noms comme distanceKm et tempC rendent aussi les unités visibles.
Points clés
- Lis un chemin imbriqué depuis son objet extérieur jusqu’à la valeur recherchée.
findrenvoie l’enregistrement existant, pas une copie.?.s’arrête sur un maillon nul ou indéfini ;??fournit une solution de repli pour une valeur nulle ou indéfinie.- Utilise un tableau pour une liste ordonnée et des données associées à des clés pour une recherche directe.
Object.groupByregroupe des enregistrements dans des tableaux associés à des clés.- Des noms de champs, des types et des unités cohérents facilitent le traitement des enregistrements.
2Donne des comportements aux objets avec des méthodes et this
Les méthodes permettent à un objet de combiner ses données avec des actions qui les utilisent. Le petit mot this relie une action à un objet, mais sa valeur dépend de la façon dont la fonction s’exécute. Tu suivras les appels de méthode ordinaires, les méthodes empruntées et les fonctions de rappel, puis tu choisiras une fonction enveloppante ou une fonction liée lorsqu’une action doit conserver son objet. Les exemples s’exécutent comme des modules : le mode strict s’applique donc sauf si un exemple utilise explicitement du code non strict.
2.1 Écris des méthodes qui utilisent les données de leur objet
Une méthode est une propriété dont la valeur est une fonction, appelée par l’intermédiaire d’un objet. Elle permet à une action d’utiliser les données actuelles de l’enregistrement.
Écrire une méthode avec this
const counter = {
count: 0,
increment() {
this.count += 1;
return this.count;
}
};
counter.increment(); // 1
counter.increment(); // 2
La notation abrégée increment() { ... } définit une propriété dont la valeur est une fonction classique. Dans counter.increment(), l’objet receveur counter devient this. Chaque appel lit le compte stocké, ajoute un et renvoie le nouveau nombre.
Un count sans préfixe désigne une variable, pas la propriété. Sans variable correspondante, count += 1 lève une ReferenceError. Utilise this.count pour accéder au champ de l’objet receveur.
Lire une fonction ou l’exécuter
counter.increment lit une valeur de type "function". Les parenthèses dans counter.increment() l’exécutent et donnent sa valeur de retour. Lorsqu’une action est transmise pour être utilisée plus tard, le code qui la reçoit a besoin de la fonction, pas du résultat de son exécution immédiate.
Les méthodes intégrées utilisent aussi cette forme d’appel : Math.max(3, 7) renvoie 7 et "abc".toUpperCase() renvoie "ABC".
Réutiliser une action
function describe() {
return this.name + " (" + this.year + ")";
}
const film = { name: "Up", year: 2009, describe };
const song = { name: "Hello", year: 2015, describe };
film.describe() renvoie "Up (2009)" ; song.describe() renvoie "Hello (2015)". L’utilisation de this permet à la même fonction de lire les données de l’un ou l’autre objet receveur. Écrire film.name en dur la lierait à la variable film.
Renvoyer l’objet receveur pour une autre action
const playlist = {
tracks: [],
add(title) { this.tracks.push(title); return this; },
count() { return this.tracks.length; }
};
playlist.add("Rain").add("Waves").count(); // 2
Chaque appel à add renvoie la liste de lecture, ce qui permet de rechercher la méthode suivante sur cet objet. Renvoyer un nombre depuis add interromprait la chaîne, car l’appel suivant à add serait recherché sur ce nombre.
La conversion JSON ordinaire omet les méthodes : la conversion de { name: "Kit", hi() { return 1; } } en chaîne n’écrit que name. L’analyse ne peut pas restaurer le code omis. Les enregistrements destinés à être sauvegardés ou échangés conservent souvent des données simples et utilisent des fonctions de traitement distinctes.
Points clés
- Une méthode est une propriété dont la valeur est une fonction, appelée par l’intermédiaire d’un objet.
- Dans
obj.method(), une méthode classique utiliseobjcommethis. - Une valeur qui est une fonction et le résultat de son appel sont des valeurs différentes.
- Renvoyer
thispeut permettre d’enchaîner un autre appel de méthode. - La conversion JSON ordinaire omet les propriétés dont la valeur est une fonction.
2.2 Explique comment la valeur de this est déterminée
Pour une fonction classique, l’appel détermine this. Stocker une fonction dans un objet ne la lie pas définitivement à cet objet.
Suivre l’objet receveur lors de l’appel
const a = { n: "A", who() { return this.n; } };
const b = { n: "B" };
b.who = a.who;
a.who(); // "A"
b.who(); // "B"
Les deux propriétés contiennent la même fonction. L’objet receveur avant le point diffère, les résultats diffèrent donc aussi. L’emplacement d’origine de la fonction ne détermine pas l’objet dont elle lit les données.
Pour un appel simple, f(), le mode strict fournit undefined comme this. Les modules JavaScript s’exécutent toujours en mode strict ; un script ou une fonction peut aussi commencer par "use strict";. Une fonction classique non stricte appelée simplement utilise à la place l’objet global, globalThis. Dans un navigateur, cet objet global est window.
Reconnaître le contexte environnant d’une fonction fléchée
Une fonction fléchée n’a pas de this propre. Elle conserve le this du code environnant où elle a été créée. Un littéral d’objet ne crée pas de nouveau contexte this.
// At the top level of a module:
const user = {
name: "Ida",
hi: () => "Hi, " + this.name
};
Appeler user.hi() lève une TypeError : la fonction fléchée a capturé le this du niveau supérieur du module, qui vaut undefined. Modifier l’appel pour lui donner la forme d’un appel de méthode ne peut pas donner un nouvel objet receveur à la fonction fléchée. Au niveau supérieur d’un script classique, le this environnant est en revanche l’objet global.
Utilise une méthode classique lorsque l’action a besoin de l’objet appelant. Utilise une fonction fléchée dans cette méthode lorsqu’une fonction de rappel doit conserver le contexte de la méthode :
const group = {
title: "Team",
members: ["Ana", "Ben"],
list() {
return this.members.map(m => this.title + ": " + m);
}
};
group.list(); // ["Team: Ana", "Team: Ben"]
list reçoit group lors de son appel comme méthode. La fonction fléchée est créée dans cette méthode en cours d’exécution et conserve le même this. Une fonction de rappel classique en mode strict, sans objet receveur fourni, recevrait undefined ; this.title échouerait donc dans ce cas.
Suivre un ordre de décision
Lorsque tu rencontres un appel, identifie d’abord la fonction appelée :
- Une fonction fléchée conserve son
thisenvironnant ;call,applyetbindne peuvent pas le remplacer. - Une fonction classique liée conserve son
thislié, même aveccallouapply. - Une fonction classique non liée appelée avec
callouapplyutilise lethisfourni. - Un appel ordinaire
obj.method()utiliseobj. - Un appel simple de fonction classique utilise
undefineden mode strict ou l’objet global en mode non strict.
Les fonctions de rappel peuvent recevoir un objet receveur fourni par leur appelant. Par exemple, un écouteur d’événements DOM classique enregistré avec addEventListener reçoit comme this l’élément sur lequel il est enregistré. Examine comment le code qui reçoit une fonction de rappel l’appelle avant de supposer qu’il s’agit d’un appel simple.
Points clés
- Une fonction classique reçoit
thisde son appel : emprunter une méthode change donc son objet receveur. - Un appel simple en mode strict utilise
undefinedcommethis. - Une fonction fléchée conserve le
thisqui l’entoure à l’endroit où elle a été créée. - Un objet receveur lié prend le pas sur un appel ultérieur à
callouapply. - Une fonction fléchée dans une méthode classique peut conserver le
thisde cette méthode.
2.3 Conserve la valeur de this lorsque tu passes des méthodes comme fonctions de rappel
Extraire une méthode de son objet conserve la fonction, mais fait perdre l’expression d’appel d’origine. Une fonction de rappel doit être appelée de manière à recevoir l’objet dont elle a besoin.
Diagnostiquer une méthode détachée
const counter = {
count: 0,
increment() {
this.count += 1;
return this.count;
}
};
const inc = counter.increment;
inc(); // TypeError in strict mode
inc() est un appel simple, donc this vaut undefined. La lecture de this.count échoue avant toute incrémentation. Dans du code non strict, un appel simple utilise l’objet global et peut écrire à la place dans un count global ; il n’accède pas au compteur.
Le même problème apparaît dans les fonctions de rappel des méthodes de tableau. [1, 2].map(counter.increment) fournit une fonction à map sans son objet receveur d’origine. Les valeurs du tableau passées comme arguments ne fournissent pas this.
Envelopper l’appel de méthode
const results = [1, 2].map(() => counter.increment());
// results is [1, 2]; counter.count is 2
La fonction de rappel est une fonction fléchée qui effectue un appel normal à counter.increment(). Cet appel possède un objet receveur. La fonction enveloppante ignore volontairement les valeurs passées par map ; chaque invocation incrémente simplement le compteur une fois. Cette forme est pratique lorsque la fonction de rappel ne sert qu’à un seul endroit.
Lier une fonction réutilisable
En repartant d’un nouveau compteur à zéro :
const boundInc = counter.increment.bind(counter);
const results = [1, 2].map(boundInc);
// results is [1, 2]; counter.count is 2
bind renvoie une nouvelle fonction ; il n’appelle pas encore la méthode. La nouvelle fonction conserve counter comme objet receveur. La lier à nouveau avec un autre objet ne peut pas remplacer cet objet receveur. Chaque appel à bind crée une fonction distincte : enregistre donc le résultat lorsque le code devra reconnaître exactement la même fonction de rappel plus tard.
La liaison peut aussi fixer les premiers arguments. function multiply(a, b) { return a * b; } suivi de const double = multiply.bind(null, 2); fait que double(21) renvoie 42. null occupe la place de l’objet receveur car cette fonction n’utilise pas this ; 2 remplit son premier paramètre ordinaire.
Exécuter une fois avec call ou apply
function describe(unit) {
return this.value + " " + unit;
}
describe.call({ value: 12 }, "kg"); // "12 kg"
describe.apply({ value: 12 }, ["kg"]); // "12 kg"
Les deux formes s’exécutent immédiatement avec l’objet receveur choisi. call fournit les arguments séparément ; apply les fournit dans un tableau. Le contexte d’une fonction fléchée est fixé par son environnement, donc ces méthodes ne peuvent pas remplacer son this.
Passer counter.increment() comme fonction de rappel exécute immédiatement la méthode et transmet le nombre qu’elle renvoie. Ce n’est pas la fonction dont map a besoin. Lors d’un enregistrement d’événement comme button.addEventListener("click", counter.increment()), le compteur change immédiatement et l’écouteur numérique provoque une TypeError. Passe une valeur qui est une fonction, une fonction fléchée enveloppante ou une fonction liée conservée dans une variable.
Points clés
- Détacher une méthode lui fait perdre son objet receveur d’origine.
- Une fonction fléchée enveloppante peut effectuer plus tard l’appel de méthode nécessaire.
bindcrée une fonction avec un objet receveur fixe et, éventuellement, des premiers arguments fixés.calletapplyexécutent immédiatement la fonction ; le format de leurs arguments diffère.- Les arguments qui servent de fonctions de rappel doivent être des fonctions, pas le résultat numérique de l’exécution d’une méthode.
3Extrais et combine des données avec la déstructuration, la décomposition et le reste
La déstructuration donne des noms à des éléments choisis dans un objet ou une collection ordonnée. La décomposition construit des valeurs à partir d’éléments existants, tandis que le reste regroupe les éléments restants. Ces formes apparaissent souvent ensemble dans des fonctions qui reçoivent des options ou renvoient des enregistrements mis à jour. Examiner attentivement leur position te permet de prévoir quelles variables existent, quelles valeurs par défaut s’appliquent et si les données imbriquées sont partagées avec l’original.
3.1 Déstructure des objets
La déstructuration d’objet lit des champs nommés dans des variables locales. Elle sélectionne des valeurs sans copier tout l’enregistrement source.
Faire correspondre et renommer
const book = { title: "Dune", pages: 412 };
const { pages, title: bookTitle, rating: stars = 0 } = book;
La correspondance se fait par nom de propriété, pas selon l’ordre. Cela déclare pages avec la valeur 412, bookTitle avec "Dune" et stars avec 0. Aucune variable title ou rating n’est déclarée : le nom après les deux-points est la variable locale cible.
Un champ absent fournit undefined. Une valeur par défaut remplace uniquement undefined et préserve null, zéro, false et les chaînes vides. const { a = 5 } = { a: null }; laisse donc a à null.
Suivre les champs imbriqués
const data = {
location: { name: "Oslo" },
current: { tempC: -3, windKph: 18 }
};
const {
location: { name },
current: { tempC, windKph: wind }
} = data;
Les variables déclarées sont name, tempC et wind, avec les valeurs "Oslo", -3 et 18. Les noms englobants location et current sélectionnent des chemins ; ils ne deviennent pas eux-mêmes des variables.
Un objet extérieur absent fait échouer une lecture imbriquée. const { shipping: { date } } = {}; lève une TypeError. Fournis une valeur par défaut au niveau extérieur lorsque ce champ peut être undefined :
const { shipping: { date } = {} } = {};
// date is undefined
Cela ne remplace pas shipping lorsque sa valeur est null. Déstructurer directement null ou undefined lève aussi une erreur : la source doit donc être utilisable avant le début de l’extraction.
Recevoir des options nommées
function formatUser({ name, age = "unknown" }) {
return name + ", " + age;
}
formatUser({ name: "Mo" }) renvoie "Mo, unknown". Changer l’ordre des champs dans { age: 40, name: "Ines" } renvoie toujours "Ines, 40". Appeler formatUser sans argument échoue car il n’y a pas d’objet à déstructurer. Une valeur par défaut pour l’ensemble du paramètre permet cet appel :
function greet({ name = "guest" } = {}) {
return "Hi, " + name;
}
greet(); // "Hi, guest"
La valeur par défaut extérieure traite un argument omis ; la valeur par défaut intérieure traite un nom absent. Passer null échoue toujours. Pour affecter des valeurs à des variables existantes, entoure de parenthèses une instruction avec un motif objet : let x, y; ({ x, y } = { x: 4, y: 7 });. Sinon, les accolades initiales sont interprétées comme un bloc d’instructions.
Points clés
- Les motifs objet font correspondre les propriétés par leur nom.
- Les deux-points renomment la variable ; ils ne changent pas la clé source.
- Les valeurs par défaut remplacent
undefined, notamment pour les propriétés absentes, et préserventnull. - Les motifs imbriqués nécessitent un objet utilisable à chaque niveau.
- Une valeur par défaut pour l’ensemble d’un paramètre et une valeur par défaut pour une propriété traitent des valeurs absentes différentes.
- Les parenthèses permettent à un motif objet d’affecter des valeurs à des variables existantes.
3.2 Déstructure des tableaux et d’autres itérables
La déstructuration de tableau lit les valeurs d’un itérable selon leur position. Les virgules déterminent quelles valeurs sont sélectionnées ; les noms des variables ne choisissent pas les positions.
Sélectionner ou ignorer des positions
const medals = ["gold", "silver", "bronze"];
const [first, second] = medals;
const [, , third] = medals;
Les variables reçoivent "gold", "silver" et "bronze". Les emplacements vides consomment des valeurs sans déclarer de variables. Un nom situé au-delà des valeurs disponibles reçoit undefined. Les valeurs par défaut ne remplacent que undefined :
const [p, q = 10] = [1]; // p is 1; q is 10
const [r = 10] = [null]; // r is null
Regrouper les valeurs restantes
const [head, ...tail] = [1, 2, 3, 4];
// head is 1; tail is [2, 3, 4]
L’élément du reste placé en dernier crée un nouveau tableau, vide lorsqu’il ne reste rien. Il doit être en dernière position. Les valeurs qui sont des objets dans ce tableau conservent leur identité ; les regrouper ne les clone pas en profondeur.
Lire une paire renvoyée ou échanger des variables
function minMax(nums) {
return [Math.min(...nums), Math.max(...nums)];
}
const [lo, hi] = minMax([4, 9, 1]);
// lo is 1; hi is 9
L’appelant suit l’ordre convenu par la fonction qui renvoie les valeurs. Lorsqu’il y a de nombreux champs de résultat, les propriétés nommées d’un objet évitent de devoir mémoriser les positions.
Avec let x = 1, y = 2;, [x, y] = [y, x]; échange les variables. Le tableau de droite est évalué sous la forme [2, 1] avant l’une ou l’autre affectation, ce qui préserve les deux anciennes valeurs sans variable temporaire.
Extraire les valeurs d’autres itérables
Les chaînes de caractères et les Set peuvent aussi être déstructurés : const [initial] = "Zoe"; donne "Z". Les Set fournissent les valeurs dans leur ordre d’insertion. Les entrées de Map sont des paires ordonnées :
const distances = new Map([["park", 2], ["lake", 5]]);
for (const [place, distanceKm] of distances) {
console.log(place, distanceKm);
}
La boucle reçoit une paire, puis le motif sépare sa clé et sa valeur. Object.entries fournit des paires de même forme.
Un objet simple n’est pas itérable : const [name] = { name: "Ana" }; lève donc une TypeError. Utilise des accolades pour sélectionner son champ nommé : const { name } = { name: "Ana" };. Les crochets nécessitent une séquence de valeurs ; les accolades sélectionnent les propriétés par leur nom.
Points clés
- Les motifs de tableau associent les valeurs par position, et les emplacements vides ignorent des valeurs.
- Une position absente donne
undefinedsauf si une valeur par défaut le remplace. - Un élément du reste placé en dernier regroupe les valeurs restantes dans un nouveau tableau.
- Les motifs de tableau fonctionnent aussi sur les chaînes de caractères, les Set et les entrées de Map.
3.3 Copie, fusionne et regroupe des données avec la décomposition et le reste
Les trois points, ..., ont deux fonctions apparentées. La décomposition développe des données existantes dans une valeur ou un appel. Le reste regroupe des valeurs dans une variable déclarée par un motif ou un paramètre.
Fusionner selon l’ordre de priorité
const defaults = { lang: "en", units: "metric", alerts: true };
const user = { lang: "pt", alerts: false };
const options = { ...defaults, ...user };
// { lang: "pt", units: "metric", alerts: false }
La décomposition d’objet copie les propriétés propres énumérables. Lorsqu’une clé apparaît à nouveau, la dernière valeur l’emporte. Placer user avant defaults remplacerait les paramètres de l’utilisateur. Décomposer null ou undefined dans un objet n’ajoute rien.
Les copies par décomposition sont superficielles. Si un enregistrement imbriqué change, copie aussi ce niveau :
const settings = { theme: "dark", font: { size: 14, family: "serif" } };
const next = {
...settings,
font: { ...settings.font, size: 18 }
};
La décomposition extérieure préserve theme. La décomposition intérieure préserve family tout en remplaçant size. settings.font.size reste égal à 14 car l’enregistrement imbriqué modifié est nouveau.
Remplacer un enregistrement dans une liste
const todos = [{ id: 1, done: false }, { id: 2, done: false }];
const updated = todos.map(t =>
t.id === 2 ? { ...t, done: true } : t
);
map crée un nouveau tableau. L’élément correspondant devient un nouvel objet : updated[1].done vaut donc true tandis que todos[1].done reste à false. Le premier élément, inchangé, est réutilisé : updated[0] === todos[0] vaut true. Les mises à jour indépendantes ne nécessitent pas de copier les enregistrements inchangés.
Développer les valeurs d’un itérable
Dans un littéral de tableau ou un appel de fonction, la décomposition extrait les valeurs d’un itérable. [...a, ...b] réunit leurs valeurs dans un nouveau tableau. Math.max(...[4, 9, 1]) passe trois arguments et renvoie 9. Un objet simple ne peut pas être développé dans un tableau : [...{ a: 1 }] lève une TypeError. La décomposition d’objet et la décomposition d’itérable suivent des règles différentes quant à ce qu’elles lisent.
Regrouper les arguments ou les propriétés restantes
function total(...nums) {
return nums.reduce((sum, n) => sum + n, 0);
}
total(2, 3, 5); // 10
total(); // 0
Un paramètre du reste reçoit un véritable tableau, même lorsqu’il ne reçoit aucune valeur. Il doit être le dernier paramètre et il ne peut y en avoir qu’un seul. L’ancien objet arguments n’est pas un véritable tableau. Les fonctions fléchées n’ont pas d’arguments propre, mais elles peuvent lire la liaison d’une fonction classique englobante.
Le reste d’objet regroupe les propriétés propres énumérables qui n’ont pas déjà été sélectionnées :
const userRecord = { id: 8, name: "Rae", password: "x9!k" };
const { password, ...publicUser } = userRecord;
// publicUser is { id: 8, name: "Rae" }
Cela crée un nouvel enregistrement et laisse la source inchangée. La propriété du reste doit être en dernier. Observe leur emplacement pour distinguer leurs fonctions : trois points dans un littéral ou un appel développent des valeurs ; trois points dans une liste de paramètres ou une cible de déstructuration les regroupent.
Points clés
- Lorsque des décompositions d’objet contiennent la même clé, les dernières propriétés l’emportent.
- Copie chaque niveau imbriqué qui doit changer indépendamment.
- La décomposition dans un tableau ou un appel nécessite un itérable.
- Le reste regroupe les arguments, éléments ou propriétés restants et doit être en dernier.
- Une mise à jour avec map peut copier un enregistrement modifié tout en réutilisant les enregistrements inchangés.
- Les paramètres du reste sont de véritables tableaux ; l’ancien objet
argumentsn’en est pas un.
4Stocke des collections avec Map et Set
Certaines collections ont besoin de clés qui sont des objets ou des nombres, et d’autres doivent conserver chaque valeur une seule fois. Map et Set répondent directement à ces besoins. Tu créeras des entrées, testeras l’appartenance, suivras l’ordre d’insertion et convertiras des collections en tableaux ou en objets lorsqu’une autre opération nécessite cette structure. L’égalité compte toujours : deux enregistrements aux champs identiques peuvent rester deux valeurs distinctes dans l’une comme dans l’autre collection.
4.1 Stocke des paires clé-valeur dans une Map
Une Map stocke des associations entre des clés et des valeurs. Contrairement aux clés qui sont des chaînes dans un objet simple, une clé de Map peut être un nombre, un objet ou une autre valeur sans être convertie en chaîne de caractères.
Créer et gérer des entrées
const stock = new Map();
stock.set("apples", 12).set("pears", 7);
stock.get("apples"); // 12
stock.has("kiwis"); // false
stock.size; // 2
set ajoute une entrée ou remplace sa valeur et renvoie la Map pour permettre le chaînage. get renvoie undefined pour une clé absente ; utilise has pour distinguer ce cas d’une entrée qui stocke undefined. delete(key) indique si une entrée a été supprimée et clear() vide la collection.
La notation entre crochets utilise un espace de stockage différent : stock["plums"] = 5; ajoute une propriété ordinaire à l’objet Map. Elle ne crée pas d’entrée visible par get, has ou size. Utilise les méthodes de Map pour les entrées.
Conserver les types et les identités des clés
m.set(1, "number"); m.set("1", "text"); crée deux entrées. Dans un objet simple, les clés 1 et "1" désigneraient une seule propriété. Les clés de Map sont comparées comme avec ===, sauf que NaN correspond à lui-même et que les zéros signés partagent une même clé.
const person = { id: 1 };
const notes = new Map([[person, "ready"]]);
notes.get(person); // "ready"
notes.get({ id: 1 }); // undefined
La seconde recherche crée un nouvel objet. Des champs identiques n’en font pas la même clé. Conserve et réutilise la référence à l’objet d’origine lorsque tu utilises un objet comme clé.
Parcourir et convertir des paires
for (const [name, count] of stock) {
console.log(name, count);
}
Une Map fournit des paires [key, value] dans l’ordre de première insertion. Remplacer une valeur ne déplace pas sa clé. keys(), values() et entries() renvoient des vues itérables que tu peux parcourir avec une boucle ou décomposer dans des tableaux. forEach passe d’abord la valeur à sa fonction de rappel, puis la clé.
new Map(Object.entries(obj)) transforme les entrées d’un enregistrement en Map. Object.fromEntries(map) crée un objet ; utilise cette méthode lorsque les clés sont des chaînes, car les clés d’objet ne peuvent pas préserver tous les types de clés d’une Map. [...map] crée un tableau de paires, utile pour enregistrer les entrées d’une Map en JSON.
Compter des clés qui changent
const words = "the cat saw the dog and the bird".split(" ");
const counts = new Map();
for (const word of words) {
counts.set(word, (counts.get(word) ?? 0) + 1);
}
La première occurrence part de zéro, puis ajoute un. Les occurrences suivantes lisent et augmentent le compte stocké. counts.get("the") vaut 3 et counts.size vaut 6 : la taille compte les mots distincts, pas les huit occurrences.
Choisis un objet simple pour un enregistrement aux champs connus, surtout pour des données compatibles avec JSON. Choisis une Map pour des clés qui changent, des vérifications fréquentes de taille ou des clés dont le type doit être préservé. La méthode récente Map.groupBy préserve les types des clés de groupe :
const owner = { name: "Ari" };
const jobs = [{ owner, done: false }, { owner, done: true }];
const byOwner = Map.groupBy(jobs, job => job.owner);
byOwner.get(owner).length; // 2
Dans du code plus ancien, parcours les tâches avec une boucle. Pour chaque responsable, utilise has et set pour créer une seule fois un tableau de groupe, puis get(owner).push(job) pour ajouter l’enregistrement. Conserver le responsable comme clé objet permet de distinguer différents responsables même lorsque leurs champs de nom correspondent. Une WeakMap peut associer des métadonnées à des objets sans maintenir en mémoire les objets clés qui seraient autrement inaccessibles. Elle ne permet ni l’itération ni la lecture de sa taille. Les WeakMap modernes acceptent aussi les symboles non enregistrés comme clés.
Points clés
- Les clés de Map conservent leur type et comparent les objets par identité.
- Utilise
set,get,hasetdeletepour les entrées, pas la notation entre crochets. sizecompte les entrées et l’itération suit l’ordre d’insertion des clés.- Les Map se convertissent à l’aide de paires clé-valeur.
- Une WeakMap peut contenir des métadonnées d’objet sans maintenir les objets clés en mémoire.
Map.groupBypréserve les types des clés de groupe dans une API de regroupement récente.
4.2 Conserve des valeurs uniques dans un Set
Un Set stocke des valeurs uniques. Ses principales questions portent sur la présence d’une valeur et sur les éléments communs à deux collections.
Ajouter et tester des valeurs
const tags = new Set(["js", "css", "js"]);
tags.size; // 2
tags.add("html");
tags.has("css"); // true
Ajouter une valeur existante ne change rien. add renvoie le Set pour permettre le chaînage. delete(value) indique si la valeur a été supprimée, tandis que clear() supprime toutes les valeurs. Le constructeur prend un seul itérable : utilise new Set([1, 2, 3]). new Set(1, 2, 3) lève une TypeError car sa première entrée n’est pas itérable. Une chaîne de caractères est itérable, donc new Set("hello") contient "h", "e", "l" et "o".
Un Set n’a pas de positions indexées. tags[0] vaut undefined. Parcours-le avec for...of, appelle forEach ou convertis-le en tableau pour des opérations comme map et filter. L’itération suit l’ordre d’insertion ; supprimer une valeur puis l’ajouter à nouveau la place à la fin.
Supprimer les doublons sans trier
const unique = [...new Set([3, 1, 3, 2, 1])];
// [3, 1, 2]
Le Set conserve la première occurrence de chaque valeur. La décomposition fournit ces valeurs dans un tableau. Array.from(set) effectue la même conversion.
Les valeurs sont comparées comme avec ===, sauf que NaN correspond à lui-même ; les zéros signés comptent comme une seule valeur. Les valeurs qui sont des objets sont comparées par identité : new Set([{ id: 1 }, { id: 1 }]).size vaut 2. Pour conserver un enregistrement par identifiant, construis une Map dont les clés sont ces identifiants, puis lis ses valeurs. Les enregistrements ultérieurs ayant le même identifiant remplacent les précédents, car set met à jour une entrée existante.
Pour les tests d’appartenance répétés dans de grandes collections, un Set évite le parcours élément par élément effectué par includes sur un tableau. Utilise-le lorsque la présence compte plus que la position.
Comparer deux collections
Les méthodes récentes de Set sont disponibles dans les principaux navigateurs depuis 2024. Avec a contenant 1, 2, 3, 4 et b contenant 3, 4, 5 :
| Opération | Sens | Valeurs obtenues |
|---|---|---|
a.union(b) | Dans l’une ou l’autre collection | 1, 2, 3, 4, 5 |
a.intersection(b) | Dans les deux | 3, 4 |
a.difference(b) | Dans a mais pas dans b | 1, 2 |
a.symmetricDifference(b) | Dans exactement une des deux | 1, 2, 5 |
Ces méthodes renvoient de nouveaux Set. isSubsetOf vérifie que chaque valeur est dans l’autre collection. isSupersetOf vérifie l’inclusion inverse. isDisjointFrom vérifie que les collections n’ont aucune valeur en commun. Les trois renvoient des booléens. Par exemple, new Set([3, 4]).isSubsetOf(a) est vrai. La différence a un sens : les valeurs présentes dans b mais pas dans a se limiteraient à 5.
Dans un environnement plus ancien, une intersection peut s’écrire new Set([...a].filter(x => b.has(x))).
L’appel ordinaire à JSON.stringify(set) produit "{}", ce qui fait perdre les valeurs stockées. Convertis le Set en tableau avant d’écrire du JSON, puis utilise new Set(parsedArray) à la lecture. Un WeakSet peut marquer des objets comme traités sans maintenir en mémoire ceux qui seraient autrement inaccessibles. Il ne peut pas être parcouru par itération. Les WeakSet modernes acceptent aussi les symboles non enregistrés.
Points clés
- Un Set stocke chaque valeur distincte une seule fois et teste sa présence avec
has. - Convertis un Set en tableau pour accéder à ses éléments par indice ou utiliser des méthodes de tableau.
- Les valeurs qui sont des objets restent distinctes sauf si leurs références correspondent.
- L’union, l’intersection, la différence et la différence symétrique répondent à des questions d’appartenance différentes.
- La différence dépend du Set placé en premier.
- Convertis les valeurs d’un Set en tableau avant d’écrire du JSON.
- WeakSet peut marquer des objets sans les maintenir en mémoire.
5Convertis des données en JSON et inversement
JSON transporte des données structurées sous forme de texte. Convertir ce texte en valeurs JavaScript et inversement n’est utile que si tu sais quelles informations survivent à la conversion. Tu reconnaîtras du JSON valide, contrôleras la façon dont les valeurs sont écrites et traiteras les entrées mal formées lors de leur lecture. Une analyse réussie doit aussi être suivie d’une vérification de structure avant que le programme utilise les champs ; un texte valide ne suffit pas à garantir que les données sont celles attendues.
5.1 Lis et écris au format JSON
JSON, abréviation de JavaScript Object Notation, est un format texte indépendant des langages pour les données structurées. Un objet est une valeur JavaScript utilisable dans le programme ; JSON est du texte qui peut décrire une telle valeur.
Reconnaître les six types de valeurs
JSON prend en charge les objets, les tableaux, les chaînes de caractères, les nombres, les booléens et null. Chacun peut être la valeur au niveau supérieur. Le texte 42 est du JSON valide même sans accolades. JSON ne représente pas les fonctions, undefined, les dates comme type distinct, Map, Set, NaN ou Infinity.
{
"name": "Amara",
"age": 34,
"languages": ["en", "yo"],
"address": null,
"member": true
}
Les mêmes principes de structure apparaissent dans les littéraux JavaScript, mais les règles d’écriture autorisées sont plus strictes. JSON est utilisé dans les configurations et les échanges de données. Le JSON échangé utilise l’encodage UTF-8 et le type de média application/json ; les fichiers JSON utilisent l’extension .json.
Appliquer les règles de syntaxe
Chaque clé d’objet doit être une chaîne de caractères entre guillemets doubles. Les chaînes nécessitent aussi des guillemets doubles. Les virgules séparent les propriétés ou les éléments de tableau, mais aucune virgule ne peut suivre le dernier. Les commentaires sont interdits. Les espaces entre les valeurs et les signes de ponctuation sont autorisés.
| Texte | Pourquoi il est invalide |
|---|---|
{name: "Amara"} | La clé n’a pas de guillemets doubles. |
{'name': 'Amara'} | Les guillemets simples ne délimitent pas les chaînes JSON. |
{"a": 1,} | La virgule finale n’est suivie d’aucune propriété. |
{"a": undefined} | Undefined n’est pas une valeur JSON. |
Les nombres utilisent la notation décimale. 1.5e3, -0.25 et 0 sont valides. 07, +1 et 0x1F sont invalides car JSON interdit les zéros initiaux, le signe plus initial et la notation hexadécimale.
Échapper les caractères dans les chaînes
Utilise \" pour un guillemet double, \\ pour une barre oblique inverse, \n pour une nouvelle ligne et \t pour une tabulation dans une chaîne JSON. Un saut de ligne brut ne peut pas apparaître dans une chaîne JSON. Laisse JSON.stringify générer les séquences d’échappement à partir des valeurs réelles des chaînes afin que les guillemets qu’elles contiennent ne puissent pas rendre le résultat invalide.
Une séquence d’échappement Unicode comprend une barre oblique inverse, la lettre u et quatre chiffres hexadécimaux pour une unité de code UTF-16. Par exemple, \u00e9 représente é. Un caractère au-delà de cette plage peut nécessiter deux séquences de ce type ; il peut aussi être écrit directement dans la chaîne. Les guillemets autour du texte JSON dans le code source JavaScript constituent un niveau distinct des guillemets à l’intérieur du JSON lui-même.
Préserver les identifiants et éviter les clés en double
Les nombres JavaScript préservent chaque entier de l’intervalle sûr allant de -9 007 199 254 740 991 à 9 007 199 254 740 991. En dehors de cet intervalle, certains entiers restent exacts et d’autres sont arrondis. L’analyse de '{"id":9007199254740993}' donne à id la valeur 9007199254740992. Stocke les identifiants longs sous forme de chaînes JSON lorsque leurs chiffres exacts doivent être préservés.
Les clés devraient être uniques dans chaque objet JSON. En JavaScript, JSON.parse conserve la dernière occurrence lorsqu’une clé est répétée : l’analyse de '{"a":1,"a":2}' produit { a: 2 }. Les propriétés distinctes ne peuvent pas être récupérées à partir de ce nom répété.
Points clés
- JSON est du texte avec six types de valeurs, y compris des valeurs primitives au niveau supérieur.
- Les clés et les chaînes nécessitent des guillemets doubles ; les commentaires et les virgules finales sont invalides.
- Les nombres JSON excluent la notation hexadécimale, les signes plus initiaux et les zéros initiaux.
- Les séquences d’échappement représentent des caractères spéciaux dans les chaînes.
- Utilise des chaînes de caractères pour les identifiants longs dont les chiffres exacts doivent être préservés.
- Les clés d’objet répétées posent problème ;
JSON.parseconserve la dernière valeur.
5.2 Convertis des valeurs en texte JSON avec JSON.stringify
JSON.stringify convertit les valeurs JavaScript prises en charge en texte JSON. Détermine ce que le texte doit préserver avant de convertir un enregistrement contenant des méthodes ou des valeurs qui sont des collections.
Écrire du texte compact ou indenté
const person = { name: "Amara", age: 34, tags: ["admin"] };
const text = JSON.stringify(person);
// '{"name":"Amara","age":34,"tags":["admin"]}'
Le résultat est une chaîne de caractères, donc typeof text vaut "string". Les propriétés propres énumérables dont les clés sont des chaînes sont écrites dans l’ordre de Object.keys. JSON.stringify(person, null, 2) ajoute des sauts de ligne et deux espaces d’indentation par niveau. Le deuxième argument est null car aucun paramètre replacer n’est utilisé. L’indentation numérique est limitée à 10 espaces ; une chaîne utilisée pour l’indentation est limitée à ses 10 premiers caractères.
Prévoir les valeurs omises et modifiées
const data = {
a: undefined,
b: () => 1,
c: NaN,
d: [undefined, Infinity]
};
JSON.stringify(data); // '{"c":null,"d":[null,null]}'
Une propriété d’objet contenant undefined, une fonction ou un symbole est omise. Dans un tableau, une telle valeur devient null, ce qui préserve cette position. NaN et Infinity deviennent null dans les deux cas. Au niveau supérieur, les valeurs non prises en charge comme undefined ou une fonction font renvoyer undefined à stringify, et non du texte JSON.
Une Date écrit sa chaîne ISO en UTC par l’intermédiaire de toJSON. Les entrées ordinaires de Map et de Set ne sont pas écrites : chacune de ces collections devient donc {}. Convertis les valeurs de Set en tableau et les entrées de Map en paires ou en objet dont les clés sont des chaînes avant de les écrire.
Une référence circulaire et un BigInt ordinaire comme 10n provoquent une TypeError. Les références partagées qui ne forment pas de cycle peuvent être sérialisées, mais JSON ne préservera pas leur identité partagée.
Choisir les données avec un paramètre replacer
const user = { name: "Rae", email: "rae@example.com", password: "x9!k", age: 31 };
JSON.stringify(user, ["name", "email"]);
// '{"name":"Rae","email":"rae@example.com"}'
Un tableau utilisé comme paramètre replacer sélectionne les noms de propriétés. Une fonction utilisée comme paramètre replacer transforme les valeurs au fur et à mesure de leur parcours, en commençant par l’entrée entière sous la clé "" :
JSON.stringify(user, (key, value) =>
key === "password" ? undefined : value
);
Renvoyer undefined omet une propriété d’objet, donne null à une position de tableau ou produit un résultat global undefined lorsque cette valeur est renvoyée pour la racine. Renvoie la valeur inchangée pour les données que tu veux conserver.
La méthode toJSON() d’un objet peut choisir sa représentation. Pour { celsius: 21, toJSON() { return { c: this.celsius }; } }, la conversion en chaîne écrit '{"c":21}'.
Ne construis pas du JSON en assemblant toi-même des chaînes entre guillemets : les guillemets ou sauts de ligne qu’elles contiennent peuvent rendre la syntaxe invalide. Ne convertis pas non plus en chaîne du texte déjà sérialisé en attendant une représentation d’objet. Convertir '{"a":1}' en chaîne encode une chaîne de caractères ; analyser ce résultat une fois renvoie une chaîne, pas un objet.
Points clés
JSON.stringifyrenvoie généralement du texte JSON ; les valeurs non prises en charge au niveau supérieur peuvent donnerundefined.- Les propriétés d’objet non prises en charge disparaissent, tandis que les éléments de tableau non pris en charge deviennent
null. - Les dates deviennent des chaînes de caractères ; Map et Set nécessitent une conversion explicite.
- Les structures circulaires et les BigInt ordinaires provoquent une
TypeError. - Les paramètres replacer et
toJSONcontrôlent la représentation écrite. - Convertir à nouveau du texte JSON en chaîne encode une chaîne, pas l’objet qu’elle contient.
5.3 Convertis du texte JSON en valeurs avec JSON.parse
JSON.parse lit du texte JSON et renvoie la valeur qu’il décrit. L’analyse vérifie la syntaxe du texte ; vérifier si le résultat convient à ton programme est une tâche distincte.
Lire la valeur, puis examiner ses champs
const data = JSON.parse('{"city":"Lima","tempC":19.5}');
data.tempC + 1; // 20.5
Les guillemets simples extérieurs délimitent une chaîne JavaScript. Les guillemets doubles à l’intérieur appartiennent au JSON. L’analyse crée un objet simple avec une propriété tempC numérique. Un texte décrivant un tableau produit un tableau ; les textes JSON primitifs produisent les valeurs primitives correspondantes.
Des données qui sont déjà un objet n’ont pas besoin d’être analysées. JSON.parse({ a: 1 }) convertit d’abord cet argument en "[object Object]", puis lève une SyntaxError. JSON.parse(undefined) échoue aussi car "undefined" n’est pas du texte JSON valide.
Gérer le texte invalide
function safeParse(text, fallback) {
try {
return JSON.parse(text);
} catch (error) {
return fallback;
}
}
safeParse("{ok:true}", null); // null
Une entrée mal formée, notamment une chaîne vide, des chaînes JSON entre guillemets simples, des clés sans guillemets et des virgules finales, provoque une SyntaxError. Intercepter cette erreur donne au programme une solution de repli choisie au lieu de l’arrêter. Une analyse réussie peut aussi donner null ; choisis donc comment l’appelant distinguera une solution de repli de données valides lorsque cette différence compte.
Restaurer certaines valeurs avec une fonction de rappel reviver
Une date stockée sous forme de texte revient sous forme de chaîne de caractères. Un tableau de paires clé-valeur reste un tableau jusqu’à ce que new Map(pairs) le transforme en Map. Les fonctions omises lors de l’écriture ne peuvent pas être récupérées à partir du texte restant.
const text = '{"title":"Dentist","due":"2026-03-01T09:00:00.000Z"}';
const event = JSON.parse(text, (key, value) =>
key === "due" ? new Date(value) : value
);
La fonction de rappel reviver parcourt les valeurs internes avant leurs contenants et termine par le résultat entier sous la clé "". Renvoyer une valeur remplace la valeur actuelle. Renvoyer undefined supprime cette propriété ; le renvoyer pour la racine donne undefined comme résultat de toute l’analyse. Oublier return value pour les autres clés peut donc effacer les données que tu voulais conserver.
Vérifier la structure et prévoir un aller-retour
Du JSON valide peut tout de même contenir des types incorrects. L’analyse de '{"temp":"19"}' laisse une chaîne de caractères : data.temp + 1 effectuerait donc une concaténation donnant "191". Vérifie les champs et les types obligatoires, par exemple avec typeof data?.temp === "number", avant de calculer. Ne convertis avec Number que lorsque le format prévu autorise une chaîne numérique ; le chaînage optionnel et ?? peuvent traiter les champs qui risquent d’être absents.
Pour const settings = { theme: "dark", volume: 0.8, recent: ["a.txt"] };, la conversion en chaîne produit 48 caractères de texte JSON. Son analyse restaure les mêmes données dans les champs, mais loaded === settings est faux car l’analyse crée de nouveaux objets. Une Date revient sous forme de chaîne, une propriété d’objet dont la valeur est undefined disparaît et un Set non converti revient sous la forme {}. Convertis les valeurs particulières avant l’écriture et restaure les types voulus après la lecture.
Points clés
JSON.parselit du texte et lève uneSyntaxErrorpour du JSON mal formé.- Une analyse réussie ne vérifie ni les champs obligatoires ni leurs types.
- Une fonction de rappel reviver parcourt d’abord les enfants et doit renvoyer les valeurs que tu veux conserver.
- Les allers-retours par JSON créent de nouveaux objets et ne préservent que les données représentables.
- Restaure explicitement les types des collections et des dates après l’analyse.
Objets JavaScript et JSON : exemples
1Suis un enregistrement d’expédition
16 étapes
- 1IntroductionConstruis un enregistrement que tu peux examiner
Une expédition associe un identifiant, une destination et des enregistrements de colis. Tu vas la construire, examiner ses champs et suivre les données partagées et copiées. Deux noms peuvent contenir une même référence vers un enregistrement, et une copie superficielle partage toujours les niveaux imbriqués : une mise à jour peut donc atteindre des données que tu voulais garder séparées.
Les exemples de l’expédition se poursuivent d’une diapositive à l’autre, sauf si une étape crée explicitement un objet distinct.
- 2ExempleCrée l’expédition
const shipment = { id: "s12", destination: "Porto", delayMin: 0 };Le littéral crée trois propriétés. Le retard est mesuré en minutes et peut valablement être nul.
shipment.destinationlit"Porto". Const autorise les mises à jour des propriétés. - 3ExempleChoisis un champ pendant l’exécution du programme
const field = "destination"; shipment[field] = "Braga"; shipment.checked = true;L’accès entre crochets évalue field et met à jour la propriété de destination. L’affectation ajoute aussi checked car cette propriété n’existait pas auparavant. L’expédition conserve la même identité ; aucune des deux opérations ne remplace l’objet extérieur. Écrire
shipment.fieldcréerait à la place une propriété distincte nommée littéralement"field". - 4DéfiLis un nom calculé
Que lit maintenant
shipment[field]et l’expédition possède-t-elle en propre une propriété field ?---reveal---
L’expression lit
"Braga". La variable field contient la clé"destination": la mise à jour et la lecture atteignent donc toutes deux cette propriété.Object.hasOwn(shipment, "field")est faux car aucune propriété littérale field n’a été créée. Une variable utilisée pour choisir une propriété ne devient pas elle-même une partie de l’enregistrement. - 5ExplicationVérifie zéro sans le perdre
shipment.delayMinvaut zéro, donc une condition qui teste si la valeur est vraie ignore son corps. La propriété existe toujours.Object.hasOwn(shipment, "delayMin")renvoie true. Utilise une vérification de propriété propre pour les champs stockés ; l’opérateur in inclut aussi les propriétés héritées. - 6ExempleLis les entrées
const pairs = Object.entries(shipment); const count = Object.keys(shipment).length;Il y a maintenant quatre champs propres énumérables dont les clés sont des chaînes de caractères, dont checked. Entries donne une paire
[key, value]pour chacun. Tu peux utiliser la bouclefor (const [key, value] of pairs)pour examiner les deux parties. Une boucle for...of directement sur l’objet simple shipment lèverait une erreur car cet objet n’est pas itérable. - 7DéfiDistingue l’existence de la valeur
Supposons que
shipment.note = undefined;soit ajouté. Que renvoientshipment.noteetObject.hasOwn(shipment, "note")?---reveal---
Ils renvoient undefined et true. L’affectation crée la propriété même si sa valeur est undefined. Supprimer la propriété donnerait false pour le test d’existence, tandis qu’une lecture ultérieure produirait toujours undefined. La valeur seule ne permet pas de distinguer ces deux situations.
- 8AnalogieSuis deux chemins vers un même enregistrement
Une référence fonctionne comme un chemin vers un enregistrement : copier le chemin donne un autre moyen d’atteindre la même destination. Cela ne construit pas un deuxième enregistrement.
const alias = shipment; alias.checked = false;shipment.checkedvaut maintenant false aussi. Les deux noms de variables atteignent un seul objet, doncalias === shipmentest vrai. Les références identiques expliquent la mise à jour partagée ; aucune étape de synchronisation n’a été exécutée entre deux copies. - 9ExempleAjoute des données qu’une copie superficielle partagera
shipment.packages = [{ massG: 450 }, { massG: 700 }]; const shallow = { ...shipment }; shallow.destination = "Faro"; shallow.packages[0].massG = 500;Le nouvel enregistrement extérieur possède sa propre destination, donc
shipment.destinationreste Braga. Sa valeur packages est la même référence au tableau qu’auparavant. Suivre ce chemin partagé modifie aussi la masse du premier colis de l’expédition d’origine, qui passe à 500. - 10ExempleCrée une copie profonde des données prises en charge
const deep = structuredClone(shipment); deep.packages[0].massG = 600;Le premier colis d’origine reste à 500 g car la copie profonde possède son propre tableau imbriqué et ses propres objets colis. Cet enregistrement ne contient que des données prises en charge. S’il contenait une propriété dont la valeur est une fonction, structuredClone lèverait une DataCloneError au lieu d’omettre silencieusement cette méthode.
- 11DéfiPrévois la portée du gel
Exécute ces instructions. L’affectation imbriquée lève-t-elle une erreur et quelle est ensuite la deuxième masse ?
Object.freeze(shipment); shipment.packages[1].massG = 750;---reveal---
Elle réussit et fixe la masse à 750. Geler shipment protège ses propriétés propres, mais pas le tableau référencé ni ses enregistrements. Réaffecter
shipment.destinationen mode strict lèverait une TypeError ; cette affectation imbriquée atteint un autre objet, qui n’est pas gelé. - 12ExempleCalcule le total actuel
const totalG = shipment.packages.reduce( (sum, pack) => sum + pack.massG, 0 );Après les mises à jour précédentes, l’expédition d’origine contient des masses de 500 et 750 g. Reduce part de zéro, ajoute 500, puis 750, ce qui donne 1 250. Le total est calculé à partir des colis actuels. Si leurs masses changent plus tard, exécute à nouveau le calcul ; ce nombre stocké ne se recalcule pas tout seul.
- 13ConseilProtège un chemin facultatif
const contactName = shipment.contact?.name ?? "Unassigned";L’enregistrement n’a pas de propriété contact : le chaînage optionnel donne donc undefined et la solution de repli fournit
"Unassigned". Ce chemin peut être absent. Laisse les champs obligatoires visibles pour la validation au lieu de remplacer silencieusement toutes les erreurs par des valeurs par défaut. La solution de repli pour les valeurs nulles ou indéfinies préserve aussi un nom volontairement vide, contrairement à une solution de repli avec OU logique. - 14DéfiConserve un zéro valide
Que renvoient
shipment.delayMin ?? 10etshipment.delayMin || 10?---reveal---
La première expression renvoie 0 ; la seconde renvoie 10. La coalescence des nuls ne remplace que null ou undefined, tandis que le OU logique remplace toute valeur fausse. Cette expédition a un retard enregistré de zéro minute : le considérer comme absent introduirait donc un retard que les données stockées n’ont jamais indiqué.
- 15DéfiCombine une copie avec une mise à jour facultative
Un nouvel enregistrement est créé avec
const next = { ...shipment };, puisnext.packages[0].massG = 520;est exécuté. Que devient la première masse de shipment et next est-il le même objet extérieur ?---reveal---
La masse d’origine passe à 520 car le tableau imbriqué est partagé.
next === shipmentest faux car la décomposition a créé un nouvel objet extérieur. Copier l’enregistrement extérieur sépare les affectations à ses propriétés propres, mais ne rend pas indépendant tout un chemin imbriqué. - 16RécapitulatifChoisis la vérification adaptée à la tâche
Choisis une propriété par une clé littérale ou calculée et distingue l’existence du caractère vrai d’une valeur. Avant une mise à jour, suis son chemin pour voir s’il atteint des données partagées.
Copie les niveaux imbriqués qui doivent être indépendants. Recalcule les totaux dérivés après modification de leurs données d’entrée.
2Garde une action liée à son objet
12 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionSuis une action lorsqu’elle est transmise
- 2ExempleCrée et appelle une action
- 3DéfiLis l’action sans l’exécuter
- 4ExempleEmprunte la fonction classique
- 5DéfiDétache la méthode empruntée
- 6Point cléPlace une fonction fléchée dans la méthode
- 7ExempleEnveloppe l’appel nécessaire
- 8ExempleLie une fonction de rappel une seule fois
- 9DéfiChoisis une exécution immédiate ou ultérieure
- 10ConseilDonne la priorité à une liaison existante
- 11DéfiSuis une méthode liée par l’intermédiaire d’un autre objet
- 12RécapitulatifLis la forme de l’appel
3Extrais des options et construis un enregistrement mis à jour
14 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionLis une syntaxe compacte par petites étapes
- 2ExempleSélectionne et renomme des champs
- 3ExempleEntre dans un motif imbriqué
- 4DéfiLis un champ imbriqué renommé
- 5DéfiDistingue null d’une valeur absente
- 6ExempleExtrais les valeurs d’une plage renvoyée
- 7ExempleRegroupe la fin dans son propre tableau
- 8DéfiÉchange les valeurs avant de les utiliser
- 9ExempleFusionne les valeurs par défaut avec celles qui les remplacent
- 10ExempleCopie le niveau imbriqué qui change
- 11LienRetire un champ du nouvel enregistrement
- 12DéfiChoisis une mise à jour indépendante
- 13DéfiRelie les motifs d’entrées à la décomposition
- 14RécapitulatifIdentifie la fonction avant de suivre les valeurs
4Suis les décomptes et l’appartenance sans doublons
11 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionChoisis ce que la collection doit mémoriser
- 2ExempleCrée des décomptes avec les méthodes de Map
- 3ConseilDistingue les entrées des propriétés
- 4DéfiGarde les types de clés distincts
- 5ExempleRéutilise une clé objet
- 6ExempleRegroupe les libellés uniques
- 7DéfiDétermine si des enregistrements sont des doublons
- 8ExempleTrouve les libellés communs et absents
- 9Point cléChange la question d’appartenance
- 10DéfiRelie les décomptes à l’appartenance
- 11RécapitulatifAdapte la structure à l’opération
5Écris, lis et vérifie des données JSON
14 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionPrévois les deux sens de conversion
- 2ExplicationLis le texte comme du texte
- 3DéfiCorrige un problème de syntaxe
- 4ExempleExamine les paramètres en mémoire
- 5ExempleConvertis la collection avant l’écriture
- 6ConseilLaisse le sérialiseur échapper les chaînes
- 7DéfiPrévois le traitement d’un élément de tableau non pris en charge
- 8ExempleAnalyse les données et restaure les opérations d’appartenance
- 9ExempleTraite délibérément le texte mal formé
- 10DéfiVérifie une valeur valide mais inadaptée
- 11ExplicationRestaure un champ avec une fonction de rappel reviver
- 12DéfiPréserve une distinction entre clés de Map
- 13LienDistingue le clonage de l’échange
- 14RécapitulatifVérifie la syntaxe, la structure et la représentation
Objets JavaScript et JSON : QCM
Série 1 : Lis des enregistrements et suis les valeurs10 Questions Pratiques
Question 1 sur 10
Que renvoie sensor[field] ?
const sensor = { tempC: 16, field: "room" };
const field = "tempC";
Afficher la réponseMasquer la réponse
"tempC", pour sélectionner la propriété qui contient 16. L’accès par notation pointée dans sensor.field lirait plutôt la propriété littérale field et renverrait "room".Question 2 sur 10
Que renvoie Object.hasOwn(record, "enabled") ?
const record = { enabled: false };
Afficher la réponseMasquer la réponse
Question 3 sur 10
Que valent record.region et record.key ?
const key = "region";
const record = { [key]: "east" };
record[key] = "west";
Afficher la réponseMasquer la réponse
"west". Aucune propriété littéralement nommée key n’est créée, donc lire record.key renvoie undefined.Question 4 sur 10
Que vaut meter.value après cet appel ?
const meter = {
value: 7,
add() { this.value += 3; }
};
meter.add();
Afficher la réponseMasquer la réponse
Question 5 sur 10
Que renvoie right.read() ?
const left = { name: "Ivo", read() { return this.name; } };
const right = { name: "Nia", read: left.read };
Afficher la réponseMasquer la réponse
right, donc this est right et le nom renvoyé est "Nia". La fonction a d’abord été écrite dans left, mais cet emplacement ne lie pas son objet receveur. Renvoyer "Ivo" reviendrait à confondre l’emplacement de stockage d’origine avec l’objet utilisé dans l’appel actuel.Question 6 sur 10
Que valent title et score après la déstructuration ?
const { name: title, score = 8 } = { name: "Reef", score: null };
Afficher la réponseMasquer la réponse
name dans la variable locale title. Sa valeur par défaut pour score n’est utilisée que pour undefined, donc le null explicite reste null. Remplacer null par 8 appliquerait à la déstructuration la règle plus large de valeur par défaut pour les valeurs nulles ou indéfinies, alors qu’elle ne se déclenche que pour undefined.Question 7 sur 10
Quelle valeur third reçoit-il ?
const [, , third] = [4, 9, 12, 18];
Afficher la réponseMasquer la réponse
Question 8 sur 10
Que valent m.size et m.get(2) ?
const m = new Map([[2, "number"], ["2", "text"]]);
Afficher la réponseMasquer la réponse
"2" occupent deux entrées distinctes. La recherche du nombre 2 renvoie "number". Une taille de 1 résulterait du traitement des deux clés comme une même chaîne, ce qui correspond au comportement de ces noms comme propriétés d’un objet ordinaire.Question 9 sur 10
Afficher la réponseMasquer la réponse
Question 10 sur 10
Quel texte est renvoyé ?
JSON.stringify({
note: undefined,
values: [undefined, NaN],
ok: false
});
Afficher la réponseMasquer la réponse
note avec la valeur null appliquerait incorrectement la règle des tableaux à une propriété d’objet ; supprimer des positions du tableau changerait sa structure.Série 2 : Applique des motifs et conserve les objets receveurs10 Questions Pratiques
Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.
Question 1 sur 10
Que renvoie trip.host?.name ?? "Guest" ?
const trip = { host: null };
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
Quelles sont les valeurs finales de a.level et de a === b ?
const a = { level: 2 };
const b = a;
b.level = 5;
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
Que valent ensuite source.mode et source.layout.width ?
const source = { mode: "day", layout: { width: 40 } };
const copy = { ...source };
copy.mode = "night";
copy.layout.width = 60;
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
Quelle fonction peut-on passer à map pour que chaque appel mette à jour tally ?
const tally = { n: 0, tick() { return ++this.n; } };
const result = ["x", "y"].map(/* callback */);
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
Ce code s’exécute au niveau supérieur d’un module. Que se passe-t-il lorsque card.read() est appelé ?
const card = { title: "Basin", read: () => this.title };
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
Après next.panel.width = 90, que valent next.mode et base.panel.width ?
const base = { mode: "wide", panel: { width: 50 } };
const next = { mode: "small", ...base, panel: { ...base.panel } };
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
Quelle valeur size reçoit-il ?
const { size = 6 } = {};
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
Quel tableau cette expression produit-elle ?
[...new Set(["red", "blue", "red", "green", "blue"])];
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
Quelle est la valeur finale de loaded ?
const loaded = JSON.parse('{"count":4,"tag":"a"}', (key, value) => {
if (key === "count") return value * 2;
});
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
Que se passe-t-il lorsque ce texte est analysé ?
JSON.parse('{"mode":"fast","mode":"slow"}');
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Série 3 : Transforme des collections et récupère des données10 Questions Pratiques
Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.
Question 1 sur 10
Quel objet l’expression crée-t-elle ?
Object.fromEntries(
Object.entries({ north: 3, south: 5 })
.map(([key, value]) => [key, value + 2])
);
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
Que renvoie options.limit ?? 12 ?
const options = { limit: 0 };
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
Que doit renvoyer add pour que basket.add("pear").add("fig") utilise deux fois le même panier ?
const basket = {
items: [],
add(item) { this.items.push(item); /* return here */ }
};
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
Quel tableau est renvoyé dans ce module ?
function scale(n) { return this.factor * n; }
const twice = scale.bind({ factor: 2 });
const obj = { factor: 9, twice };
[obj.twice(3), twice.call({ factor: 5 }, 4)];
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
Que renvoie ce code ?
function combine(first, ...others) {
return [first, others.length];
}
combine(...[7, 3, 8, 2]);
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
Que valent items[0].done, next[1] === items[1] et next === items ?
const items = [{ id: 4, done: false }, { id: 9, done: false }];
const next = items.map(item =>
item.id === 4 ? { ...item, done: true } : item
);
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
Pourquoi lookup.get({ code: 8 }) vaut-il undefined ?
const key = { code: 8 };
const lookup = new Map([[key, "ready"]]);
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
Quelles sont les tailles de a.difference(b) et de a.symmetricDifference(b) ?
const a = new Set([2, 4, 6]);
const b = new Set([4, 8]);
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
Quel texte ce code produit-il ?
JSON.stringify({ label: "Arc", count: 3 }, ["label"]);
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
Ce module s’exécute sans fonction de rappel reviver. Que valent typeof loaded.due et loaded === original ?
const original = { due: new Date("2026-07-12T00:00:00.000Z") };
const loaded = JSON.parse(JSON.stringify(original));
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Série 4 : Diagnostique les mises à jour et les appels10 Questions Pratiques
Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.
Question 1 sur 10
Que valent base.inner.n, clone.inner.n et copy.inner.n à la fin ?
const base = { inner: { n: 2 } };
const copy = { ...base };
const clone = structuredClone(base);
Object.freeze(base);
copy.inner.n = 7;
clone.inner.n = 9;
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
Quel tableau Object.keys(data) renvoie-t-il ?
const data = { z: 1, "10": 2, "02": 3, "2": 4, a: 5 };
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
Que vaut totalG et modifier heavy.massG modifie-t-il aussi load.items[1].massG ?
const load = { items: [
{ massG: 120, qty: 2 },
{ massG: 300, qty: 1 }
] };
const heavy = load.items.find(x => x.massG > 200);
const totalG = load.items.reduce((s, x) => s + x.massG * x.qty, 0);
heavy.massG = 350;
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
Que renvoie b.labels() dans ce module ?
const a = {
prefix: "A",
names: ["oak"],
labels() { return this.names.map(n => this.prefix + n); }
};
const b = { prefix: "B", names: ["elm"], labels: a.labels };
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
Que vaut typeof box.open ?
const box = { open() { return "opened"; } };
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
Que se passe-t-il lorsque read() et read({ prefs: null }) sont appelés séparément ?
function read({ prefs: { theme = "light" } = {} } = {}) {
return theme;
}
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
Que vaut tail ?
const [head, ...tail] = [6, 8, 11];
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
Que valent m.size et [...m.keys()] ?
const m = new Map([["p", 1], ["q", 2]]);
m.set("p", 4);
m["r"] = 5;
m.delete("q");
m.set("q", 6);
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
JSON.parse('{"depthM":+7}') échoue-t-il ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
Que valent result.count et result.total ?
const result = JSON.parse('{"count":"6","total":12}',
(key, value) => key === "count" ? Number(value) : value
);
result.total += result.count;
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Série 5 : Combine les choix de données et les règles de conversion10 Questions Pratiques
Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.
Question 1 sur 10
Que vaut Object.hasOwn(record, "old") après ces instructions ?
const record = { old: undefined };
delete record.old;
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
Que valent a === b, a.left === a.right et b.left === b.right ?
const shared = { n: 1 };
const a = { left: shared, right: shared };
const b = JSON.parse(JSON.stringify(a));
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
Que renvoie saved() ?
const maker = {
n: 5,
make() { return () => this.n; }
};
const other = { n: 8, make: maker.make };
const saved = other.make().bind({ n: 12 });
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
Que renvoie fixed.apply({ offset: 30 }, [4]) ?
function add(a, b) { return this.offset + a + b; }
const fixed = add.bind({ offset: 2 }, 7);
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
Que valent a, b et rest ?
let a = 3, b = 8;
[a, b] = [b, a];
const [, ...rest] = [a, b, 13];
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
Après publicCopy.profile.name = "New", que vaut source.profile.name et source possède-t-il toujours secret en propre ?
const source = { secret: "s", profile: { name: "Old" } };
const { secret, ...publicCopy } = source;
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
Quelle est la valeur finale de counts.get("moss") ?
const counts = new Map();
for (const word of ["moss", "fern", "moss", "moss"]) {
counts.set(word, (counts.get(word) ?? 0) + 1);
}
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
Que valent records.size et ids.size ?
const x = { id: 7 };
const records = new Set([x, x, { id: 7 }]);
const ids = new Set([...records].map(r => r.id));
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
Que vaut typeof JSON.parse(text) ?
const text = JSON.stringify('{"x":3}');
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
"3", avec les valeurs "n" et "s". Quelle paire de conversions les préserve lors d’un passage par JSON ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Tu bloques sur ton propre exercice ? Aide aux Devoirs
Mots-Clés
A
Aller-retour
Appel simple en mode strict
f et appeler f() dans un module peut échouer lorsqu’elle tente de lire this.name.Application partielle
multiply.bind(null, 4) crée une fonction qui multiplie son argument suivant par quatre.apply
format.apply(reading, ["m", 2]) fournit le même objet receveur et les mêmes valeurs que format.call(reading, "m", 2).Argument d’indentation
B
bind
const next = meter.step.bind(meter); crée une fonction de rappel qui conserve meter comme objet receveur.C
call
format.call(reading, "m", 2) fournit à format reading comme objet receveur et deux arguments distincts.Chaînage de méthodes
list.add("a").add("b") fonctionne lorsque le premier appel renvoie un objet doté de la méthode add suivante.Chaînage optionnel
record.owner?.name permet l’absence de owner sans tenter de lire un nom depuis undefined.Chaîne JSON
Clé d’indice de tableau
"3" est classée avant "12" dans Object.keys ; "03" reste parmi les clés de chaîne ordinaires.Coalescence des nuls
settings.volume ?? 1 conserve un volume explicitement égal à zéro, tandis que settings.volume || 1 le remplace.Copie profonde
structuredClone, modifier un champ imbriqué copié laisse le champ d’origine inchangé.Copie superficielle
D
Décomposition d’itérable
Math.max(...measurements) fournit chaque élément du tableau comme argument distinct à la fonction.Décomposition d’objet
{ ...base, active: true } copie base puis fournit la valeur finale de active.Déstructuration d’objet
const { city, tempC } = reading; crée deux variables locales à partir d’un relevé météorologique.Déstructuration de tableau
const [low, high] = bounds; suppose que bounds place sa valeur inférieure avant sa valeur supérieure.Différence
active.difference(blocked) conserve les valeurs actives qui ne figurent pas dans le Set des valeurs bloquées.Différence symétrique
Données imbriquées
report.readings[0].tempC lit une liste, son premier enregistrement, puis un champ de température.E
Entier sûr
Entrée de Map
stock.set("tea", 4) modifie une entrée ; stock["tea"] = 4 modifie une propriété ordinaire.Existence d’une propriété
count: 0 possède toujours une propriété count ; tester sa valeur comme condition ne permet pas de la repérer.É
Élément du reste dans une déstructuration de tableau
const [leader, ...others] = names; sépare le premier nom d’un tableau contenant les noms restants.F
Fonction de rappel reviver
JSON.parse qui transforme les valeurs après leurs enfants et utilise ses valeurs de retour pour les remplacer ou les supprimer.Fonction fléchée enveloppante
() => counter.tick() à map fait que chaque appel de la fonction de rappel invoque tick par l’intermédiaire de l’objet compteur.G
globalThis
I
Identité d’un objet
id: 9 sont comparés comme différents avec === malgré leurs données identiques.Intersection
Itérable
J
JSON
{"ready":true} décrit un enregistrement, tandis que true seul est aussi un texte JSON complet et valide.JSON.parse
JSON.parse lit du texte JSON et renvoie la valeur JavaScript représentée, en levant une SyntaxError lorsque le texte est mal formé.JSON.stringify
JSON.stringify sérialise les valeurs JavaScript prises en charge en texte JSON, en permettant de sélectionner les données et d’ajouter une indentation lisible.JSON.stringify(settings, null, 2) écrit une forme plus lisible sans modifier les paramètres représentés.L
Littéral d’objet
const reading = { tempC: 22 }; crée un enregistrement contenant une mesure de température.M
Map
"5" restent des entrées distinctes lorsqu’elles sont stockées dans une même Map.Map.groupBy
Map.groupBy est une méthode récente qui regroupe les éléments d’un itérable dans des tableaux au sein d’une Map, en préservant le type et l’identité des clés de groupe.Méthode
tracker.advance() exécute l’action de tracker, tandis que lire tracker.advance renvoie une fonction.Méthode détachée
const read = sensor.read; conserve la fonction, mais read() ne fournit pas sensor comme objet receveur.Méthode empruntée
b.read = a.read permet à b.read() d’utiliser les données de b lorsque la fonction lit par this.Mise à jour immuable
Motif de renommage
const { title: label } = page; crée label sans déclarer de variable appelée title.Motif imbriqué
const { owner: { name } } = item; nécessite un objet owner et ne déclare que name.N
Nom de propriété calculé
const code = "es";, { [code]: "Hola" } crée une propriété nommée "es".Notation abrégée de méthode
reset() { this.n = 0; } définit une action sans deux-points distincts ni mot-clé function.Notation entre crochets
const field = "heightM";, person[field] sélectionne la mesure de taille de la personne.Notation pointée
profile.name sélectionne toujours la propriété nommée "name", même si une variable appelée name existe.O
Object.freeze
Object.freeze empêche l’ajout, la suppression et la modification des propriétés propres d’un objet, mais ne gèle pas les objets imbriqués.Object.fromEntries
Object.fromEntries crée un objet à partir de paires clé-valeur, ce qui la rend utile après une transformation d’entrées ou d’une Map compatible.Object.groupBy
Object.groupBy est une méthode récente qui regroupe les éléments d’un itérable dans des tableaux associés à des clés choisies par une fonction de rappel, au sein d’un objet sans prototype.Objet d’options
{ color, size } permet aux appelants d’indiquer le sens de chaque paramètre sans dépendre de leur ordre.Objet receveur
account.describe(), account est l’objet receveur que la méthode utilise pour lire ses champs.Ordre d’insertion
P
Paire clé-valeur
Object.entries({ lake: 5 }) produit [["lake", 5]], prêt à être parcouru dans une boucle utilisant la clé et la valeur.Paramètre du reste
function total(...values) peut utiliser reduce sur values même lorsque l’appel ne fournit aucun argument.Paramètre replacer
Position ignorée
const [, second] = colors; ignore la première couleur et ne nomme que la valeur suivante fournie.Propriété
active dans { active: false } existe même si sa valeur est un booléen faux.Propriété en notation abrégée
city, le littéral { city } crée le même champ que { city: city }.Propriété propre
Object.hasOwn({}, "toString") est faux même si "toString" in {} est vrai.R
Référence
const backup = record; donne un autre moyen d’accéder à record sans copier ses champs.Référence circulaire
record.self = record fait lever une TypeError à JSON.stringify ordinaire pour cet enregistrement.Reste d’objet
const { password, ...publicRecord } = user; laisse user intact tout en excluant password de la copie.S
Séquence d’échappement
Sérialisation
Set
"ready" deux fois ne conserve qu’une valeur, tandis qu’ajouter deux enregistrements distincts aux champs identiques conserve les deux.Sous-ensemble
structuredClone
SyntaxError
JSON.parse.T
Test d’appartenance
map.has(key) peut trouver une entrée existante même lorsque map.get(key) renvoie undefined.this
this lexical
toJSON
U
Union
V
Valeur dérivée
Valeur par défaut de déstructuration
const { count = 2 } = { count: null };, le null explicite est conservé malgré la valeur par défaut.Vérification de structure
W
WeakMap
WeakSet
À propos de cette unité
Crée ton propre Matériel d'Étude
Transforme tes notes, diapos et documents en Guides d'Étude, Questions Pratiques, Flashcards et 6 autres outils.