Objets JavaScript et JSON : modéliser des données

Apprends à modéliser des données réelles avec des objets JavaScript : crée et modifie des propriétés, parcours-les avec une boucle et comprends pourquoi copier une variable ne copie pas l’objet auquel elle fait référence. Donne des comportements aux objets avec des méthodes et détermine à quoi le mot-clé this fait référence selon la façon dont une fonction est appelée. Extrais et combine des données avec la déstructuration, la décomposition et le reste, stocke des collections dans Map et Set, et convertis des données en texte JSON et inversement avec JSON.stringify et JSON.parse.

DébutantUnité 4 sur 9 de la formation Formation : JavaScript : DOM, événements et code asynchrone

Ce que tu vas apprendre

  1. 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 boucle
      Teste 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 comparaison
      Explique 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ées
      Lis 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.
  2. É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 objet
      Dé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ée
      Dé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 rappel
      Repère lorsqu’une méthode perd son objet et corrige le problème avec une fonction fléchée enveloppante, bind, call ou apply.
  3. 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 objets
      Extrais 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érables
      Extrais 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 reste
      Utilise 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.
  4. 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 Map
      Cré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 Set
      Crée et mets à jour un Set, supprime les doublons de tableaux et compare des collections avec des opérations ensemblistes.
  5. 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 JSON
      Reconnais 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.stringify
      Convertis 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.parse
      Analyse 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.

Objets JavaScript et JSON : cours

5 chapitres

1

Modé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é ; delete la supprime.
  • const fixe 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 :

ExpressionRé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.hasOwn vérifie les propriétés propres ; in vérifie aussi les propriétés héritées.
  • Object.entries fournit des paires clé-valeur pour les boucles et les transformations.
  • Object.fromEntries reconstruit 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.freeze empêche de modifier les propriétés propres, mais son effet est superficiel.
  • structuredClone copie 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.
  • find renvoie 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.groupBy regroupe 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.
2

Donne 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 utilise obj comme this.
  • Une valeur qui est une fonction et le résultat de son appel sont des valeurs différentes.
  • Renvoyer this peut 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 :

  1. Une fonction fléchée conserve son this environnant ; call, apply et bind ne peuvent pas le remplacer.
  2. Une fonction classique liée conserve son this lié, même avec call ou apply.
  3. Une fonction classique non liée appelée avec call ou apply utilise le this fourni.
  4. Un appel ordinaire obj.method() utilise obj.
  5. Un appel simple de fonction classique utilise undefined en 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 this de son appel : emprunter une méthode change donc son objet receveur.
  • Un appel simple en mode strict utilise undefined comme this.
  • Une fonction fléchée conserve le this qui l’entoure à l’endroit où elle a été créée.
  • Un objet receveur lié prend le pas sur un appel ultérieur à call ou apply.
  • Une fonction fléchée dans une méthode classique peut conserver le this de 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.
  • bind crée une fonction avec un objet receveur fixe et, éventuellement, des premiers arguments fixés.
  • call et apply exé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.
3

Extrais 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éservent null.
  • 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 undefined sauf 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 arguments n’en est pas un.
4

Stocke 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, has et delete pour les entrées, pas la notation entre crochets.
  • size compte 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.groupBy pré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érationSensValeurs obtenues
a.union(b)Dans l’une ou l’autre collection1, 2, 3, 4, 5
a.intersection(b)Dans les deux3, 4
a.difference(b)Dans a mais pas dans b1, 2
a.symmetricDifference(b)Dans exactement une des deux1, 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.
5

Convertis 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.

TextePourquoi 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.parse conserve 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.stringify renvoie généralement du texte JSON ; les valeurs non prises en charge au niveau supérieur peuvent donner undefined.
  • 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 toJSON contrô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.parse lit du texte et lève une SyntaxError pour 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

5 Leçons Interactives

1

Suis un enregistrement d’expédition

16 étapes
Crée, examine et copie un enregistrement imbriqué en suivant les valeurs partagées.
  1. 1
    IntroductionConstruis 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.

  2. 2
    ExempleCré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.destination lit "Porto". Const autorise les mises à jour des propriétés.

  3. 3
    ExempleChoisis 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.field créerait à la place une propriété distincte nommée littéralement "field".

  4. 4
    Dé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.

  5. 5
    ExplicationVérifie zéro sans le perdre

    shipment.delayMin vaut 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.

  6. 6
    ExempleLis 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 boucle for (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.

  7. 7
    DéfiDistingue l’existence de la valeur

    Supposons que shipment.note = undefined; soit ajouté. Que renvoient shipment.note et Object.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.

  8. 8
    AnalogieSuis 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.checked vaut maintenant false aussi. Les deux noms de variables atteignent un seul objet, donc alias === shipment est 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.

  9. 9
    ExempleAjoute 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.destination reste 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.

  10. 10
    ExempleCré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.

  11. 11
    Dé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.destination en mode strict lèverait une TypeError ; cette affectation imbriquée atteint un autre objet, qui n’est pas gelé.

  12. 12
    ExempleCalcule 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.

  13. 13
    ConseilProtè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.

  14. 14
    DéfiConserve un zéro valide

    Que renvoient shipment.delayMin ?? 10 et shipment.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é.

  15. 15
    DéfiCombine une copie avec une mise à jour facultative

    Un nouvel enregistrement est créé avec const next = { ...shipment };, puis next.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 === shipment est 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é.

  16. 16
    Ré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.

2

Garde une action liée à son objet

12 étapes
Suis les appels de méthode, le contexte capturé et les fonctions de rappel avec un petit compteur.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionSuis une action lorsqu’elle est transmise
  2. 2
    ExempleCrée et appelle une action
  3. 3
    DéfiLis l’action sans l’exécuter
  4. 4
    ExempleEmprunte la fonction classique
  5. 5
    DéfiDétache la méthode empruntée
  6. 6
    Point cléPlace une fonction fléchée dans la méthode
  7. 7
    ExempleEnveloppe l’appel nécessaire
  8. 8
    ExempleLie une fonction de rappel une seule fois
  9. 9
    DéfiChoisis une exécution immédiate ou ultérieure
  10. 10
    ConseilDonne la priorité à une liaison existante
  11. 11
    DéfiSuis une méthode liée par l’intermédiaire d’un autre objet
  12. 12
    RécapitulatifLis la forme de l’appel
3

Extrais des options et construis un enregistrement mis à jour

14 étapes
Lis les motifs de l’extérieur vers l’intérieur, puis copie uniquement les niveaux qui doivent changer indépendamment.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionLis une syntaxe compacte par petites étapes
  2. 2
    ExempleSélectionne et renomme des champs
  3. 3
    ExempleEntre dans un motif imbriqué
  4. 4
    DéfiLis un champ imbriqué renommé
  5. 5
    DéfiDistingue null d’une valeur absente
  6. 6
    ExempleExtrais les valeurs d’une plage renvoyée
  7. 7
    ExempleRegroupe la fin dans son propre tableau
  8. 8
    DéfiÉchange les valeurs avant de les utiliser
  9. 9
    ExempleFusionne les valeurs par défaut avec celles qui les remplacent
  10. 10
    ExempleCopie le niveau imbriqué qui change
  11. 11
    LienRetire un champ du nouvel enregistrement
  12. 12
    DéfiChoisis une mise à jour indépendante
  13. 13
    DéfiRelie les motifs d’entrées à la décomposition
  14. 14
    RécapitulatifIdentifie la fonction avant de suivre les valeurs
4

Suis les décomptes et l’appartenance sans doublons

11 étapes
Utilise Map pour des valeurs associées à des clés qui changent et Set pour l’appartenance, puis compare des collections.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionChoisis ce que la collection doit mémoriser
  2. 2
    ExempleCrée des décomptes avec les méthodes de Map
  3. 3
    ConseilDistingue les entrées des propriétés
  4. 4
    DéfiGarde les types de clés distincts
  5. 5
    ExempleRéutilise une clé objet
  6. 6
    ExempleRegroupe les libellés uniques
  7. 7
    DéfiDétermine si des enregistrements sont des doublons
  8. 8
    ExempleTrouve les libellés communs et absents
  9. 9
    Point cléChange la question d’appartenance
  10. 10
    DéfiRelie les décomptes à l’appartenance
  11. 11
    RécapitulatifAdapte la structure à l’opération
5

Écris, lis et vérifie des données JSON

14 étapes
Prévois une représentation compatible avec JSON, traite le texte invalide et restaure les types voulus.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionPrévois les deux sens de conversion
  2. 2
    ExplicationLis le texte comme du texte
  3. 3
    DéfiCorrige un problème de syntaxe
  4. 4
    ExempleExamine les paramètres en mémoire
  5. 5
    ExempleConvertis la collection avant l’écriture
  6. 6
    ConseilLaisse le sérialiseur échapper les chaînes
  7. 7
    DéfiPrévois le traitement d’un élément de tableau non pris en charge
  8. 8
    ExempleAnalyse les données et restaure les opérations d’appartenance
  9. 9
    ExempleTraite délibérément le texte mal formé
  10. 10
    DéfiVérifie une valeur valide mais inadaptée
  11. 11
    ExplicationRestaure un champ avec une fonction de rappel reviver
  12. 12
    DéfiPréserve une distinction entre clés de Map
  13. 13
    LienDistingue le clonage de l’échange
  14. 14
    RécapitulatifVérifie la syntaxe, la structure et la représentation

Objets JavaScript et JSON : QCM

50 Questions Pratiques en 5 séries

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";
  1. "room"
  2. 16
  3. "tempC"
  4. undefined
Afficher la réponseMasquer la réponse
Réponse : B
L’accès entre crochets utilise la valeur de field, "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 };
  1. false
  2. undefined
  3. null
  4. true
Afficher la réponseMasquer la réponse
Réponse : D
L’enregistrement possède directement enabled comme propriété propre, donc la vérification est vraie. Sa valeur stockée false ne passerait pas un test de valeur vraie, mais elle ne rend pas la propriété absente.

Question 3 sur 10

Que valent record.region et record.key ?

const key = "region";
const record = { [key]: "east" };
record[key] = "west";
  1. "west" et undefined
  2. "east" et "west"
  3. undefined et "west"
  4. "west" et "east"
Afficher la réponseMasquer la réponse
Réponse : A
La clé calculée crée region et l’affectation entre crochets lui donne "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();
  1. 7
  2. 3
  3. 10
  4. undefined
Afficher la réponseMasquer la réponse
Réponse : C
L’appel de méthode fait de meter l’objet receveur et fait passer value de 7 à 10. Le fait qu’une méthode sans return renvoie undefined n’annule pas sa mise à jour de la propriété.

Question 5 sur 10

Que renvoie right.read() ?

const left = { name: "Ivo", read() { return this.name; } };
const right = { name: "Nia", read: left.read };
  1. "Ivo"
  2. "Nia"
  3. undefined
  4. Une TypeError
Afficher la réponseMasquer la réponse
Réponse : B
La fonction classique est appelée par l’intermédiaire de 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 };
  1. "Reef" et null
  2. "Reef" et 8
  3. undefined et 8
  4. undefined et null
Afficher la réponseMasquer la réponse
Réponse : A
Le motif lit la propriété 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];
  1. 4
  2. 9
  3. 12
  4. 18
Afficher la réponseMasquer la réponse
Réponse : C
Les deux positions vides ignorent 4 et 9, ce qui laisse 12 pour third. Sélectionner 9 ne sauterait qu’une seule position ; le nom de la variable ne sélectionne pas lui-même un indice.

Question 8 sur 10

Que valent m.size et m.get(2) ?

const m = new Map([[2, "number"], ["2", "text"]]);
  1. 1 et "text"
  2. 2 et "text"
  3. 1 et "number"
  4. 2 et "number"
Afficher la réponseMasquer la réponse
Réponse : D
Une Map préserve les types des clés, donc le nombre 2 et la chaîne "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

Un fichier de données doit préserver exactement les chiffres de l’identifiant 9007199254740997 et pouvoir être analysé comme du JSON. Quel texte d’enregistrement répond à ces deux besoins ?
  1. {"id":9007199254740997,"active":true}
  2. {id:"9007199254740997",active:true}
  3. {"id":"9007199254740997","active":true}
  4. {"id":'9007199254740997',"active":true}
Afficher la réponseMasquer la réponse
Réponse : C
Les clés entre guillemets doubles et true en minuscules rendent l’enregistrement valide en JSON, et une chaîne de caractères conserve tous les chiffres de l’identifiant. Le grand entier sans guillemets est arrondi lors de l’analyse JavaScript, même si sa syntaxe est valide. Des clés sans guillemets ou des guillemets simples autour de l’identifiant ne respectent pas la syntaxe JSON.

Question 10 sur 10

Quel texte est renvoyé ?

JSON.stringify({
  note: undefined,
  values: [undefined, NaN],
  ok: false
});
  1. '{"values":[null,null],"ok":false}'
  2. '{"note":null,"values":[null,null],"ok":false}'
  3. '{"values":[],"ok":false}'
  4. '{"values":[null,null]}'
Afficher la réponseMasquer la réponse
Réponse : A
La propriété d’objet dont la valeur est undefined est omise, tandis que undefined dans un tableau devient null. NaN devient aussi null et le booléen valide false est conservé. Garder 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 };
  1. null
  2. undefined
  3. "Guest"
  4. Une TypeError
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;
  1. 5 et true
  2. 2 et false
  3. 5 et false
  4. 2 et true
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;
  1. "night" et 60
  2. "day" et 40
  3. "night" et 40
  4. "day" et 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 */);
  1. tally.tick
  2. () => tally.tick()
  3. tally.tick()
  4. () => tally.tick
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 };
  1. L’appel lève une TypeError.
  2. L’appel renvoie "Basin".
  3. L’appel renvoie undefined.
  4. L’appel lève une ReferenceError.
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 } };
  1. "small" et 50
  2. "wide" et 90
  3. "small" et 90
  4. "wide" et 50
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 } = {};
  1. undefined
  2. 6
  3. null
  4. 0
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"])];
  1. ["blue", "green", "red"]
  2. ["red", "green", "blue"]
  3. ["red", "blue", "green"]
  4. ["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;
});
  1. undefined
  2. { count: 8, tag: "a" }
  3. { count: 8 }
  4. {}
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"}');
  1. L’appel renvoie { mode: "fast" }.
  2. L’appel renvoie { mode: "slow" }.
  3. L’appel lève une SyntaxError.
  4. L’appel renvoie { mode: ["fast", "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])
);
  1. { north: 5, south: 7 }
  2. { north: 3, south: 5 }
  3. { north: 6, south: 10 }
  4. { 5: "north", 7: "south" }
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 };
  1. 12
  2. undefined
  3. 0
  4. null
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 */ }
};
  1. this.items
  2. item
  3. this.items.length
  4. this
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)];
  1. [27, 20]
  2. [6, 8]
  3. [6, 20]
  4. [27, 8]
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]);
  1. [7, 4]
  2. [[7, 3, 8, 2], 0]
  3. [7, 3]
  4. [7, 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
);
  1. true, true, false
  2. false, true, false
  3. false, false, false
  4. false, true, true
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"]]);
  1. La recherche utilise une référence à un autre objet.
  2. Map convertit les deux clés en chaînes différentes.
  3. Map ignore les clés objet lors de la création des entrées.
  4. La clé doit d’abord être convertie en texte JSON.
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]);
  1. 1 et 1
  2. 3 et 2
  3. 2 et 4
  4. 2 et 3
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"]);
  1. '{"label":"Arc","count":3}'
  2. '{"label":"Arc"}'
  3. '["label"]'
  4. '{"label":"Arc","count":null}'
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));
  1. "object" et false
  2. "string" et true
  3. "object" et true
  4. "string" et false
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;
  1. 2, 9, 7
  2. 9, 9, 9
  3. 2, 9, 2
  4. 7, 9, 7
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 };
  1. ["z", "10", "02", "2", "a"]
  2. ["2", "10", "z", "02", "a"]
  3. ["02", "2", "10", "z", "a"]
  4. ["2", "02", "10", "z", "a"]
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;
  1. 540 ; oui, il passe à 350.
  2. 590 ; oui, il passe à 350.
  3. 540 ; non, il reste à 300.
  4. 420 ; oui, il passe à 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 };
  1. ["Aoak"]
  2. ["Aelm"]
  3. ["Belm"]
  4. L’appel lève une TypeError.
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"; } };
  1. "function"
  2. "string"
  3. "object"
  4. "undefined"
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;
}
  1. Les deux appels renvoient "light".
  2. Le premier renvoie "light" ; le second lève une TypeError.
  3. Le premier lève une TypeError ; le second renvoie null.
  4. Le premier renvoie undefined ; le second renvoie null.
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];
  1. [6, 8, 11]
  2. 8
  3. [11]
  4. [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);
  1. 3 et ["p", "r", "q"]
  2. 2 et ["q", "p"]
  3. 2 et ["p", "q"]
  4. 3 et ["p", "q", "r"]
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 9 sur 10

Pourquoi JSON.parse('{"depthM":+7}') échoue-t-il ?
  1. Les nombres JSON ne peuvent pas commencer par un signe plus.
  2. Les nombres JSON ne peuvent pas être des entiers.
  3. Les noms de propriétés JSON ne peuvent pas contenir de majuscules.
  4. Les objets JSON doivent aussi contenir une chaîne de caractères.
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;
  1. "6" et "126"
  2. 6 et "126"
  3. 6 et 18
  4. undefined et NaN
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;
  1. true
  2. false
  3. undefined
  4. L’appel lève une TypeError.
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));
  1. false, true, true
  2. true, true, true
  3. false, true, false
  4. false, false, false
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 });
  1. 5
  2. 12
  3. undefined
  4. 8
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);
  1. 13
  2. 41
  3. 36
  4. NaN
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];
  1. 8, 8, [8, 13]
  2. 8, 3, [8, 3, 13]
  3. 8, 3, [3, 13]
  4. 3, 8, [8, 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;
  1. "Old" ; oui.
  2. "New" ; oui.
  3. "New" ; non.
  4. "Old" ; non.
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);
}
  1. 1
  2. 2
  3. 4
  4. 3
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));
  1. 2 et 1
  2. 1 et 1
  3. 3 et 1
  4. 2 et 2
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}');
  1. "string"
  2. "object"
  3. "number"
  4. "undefined"
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 10 sur 10

Une Map doit conserver séparément la clé numérique 3 et la clé qui est la chaîne "3", avec les valeurs "n" et "s". Quelle paire de conversions les préserve lors d’un passage par JSON ?
  1. Écrire JSON.stringify(Object.fromEntries(m)) ; lire avec new Map(Object.entries(JSON.parse(text))).
  2. Écrire JSON.stringify([...m]) ; lire avec new Map(JSON.parse(text)).
  3. Écrire JSON.stringify(m) ; lire avec new Map(Object.entries(JSON.parse(text))).
  4. Écrire JSON.stringify([...m.keys()]) ; lire avec new Map(JSON.parse(text)).
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

79 Mots-Clés, chacun avec sa définition

A

Aller-retour
Un aller-retour écrit des données dans une représentation puis les relit, en ne préservant que les informations que cette représentation peut exprimer.
Un aller-retour par JSON crée de nouveaux objets et renvoie une Date sous forme de texte, sauf si une conversion restaure son type.
Appel simple en mode strict
Un appel simple en mode strict invoque une fonction classique stricte sans fournir d’objet receveur, ce qui laisse sa valeur this à undefined.
Détacher une méthode dans f et appeler f() dans un module peut échouer lorsqu’elle tente de lire this.name.
Application partielle
L’application partielle fixe certains arguments immédiatement afin de créer une fonction qui recevra les arguments restants lors d’un appel ultérieur.
multiply.bind(null, 4) crée une fonction qui multiplie son argument suivant par quatre.
apply
apply exécute immédiatement une fonction avec une valeur this explicite et un tableau contenant ses arguments ordinaires.
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
L’argument d’indentation est le troisième argument de stringify ; il contrôle les espaces ou la courte chaîne utilisés pour mettre en forme le texte JSON imbriqué.
Passer null comme paramètre replacer et 2 comme troisième argument fait utiliser deux espaces à chaque niveau imbriqué.

B

bind
bind renvoie une nouvelle fonction avec une valeur this fixe et, éventuellement, des premiers arguments fixés ; l’exécution attend l’appel de la nouvelle fonction.
Enregistrer const next = meter.step.bind(meter); crée une fonction de rappel qui conserve meter comme objet receveur.

C

call
call exécute immédiatement une fonction avec une valeur this explicite, suivie des arguments ordinaires fournis un par un.
format.call(reading, "m", 2) fournit à format reading comme objet receveur et deux arguments distincts.
Chaînage de méthodes
Le chaînage de méthodes consiste à appeler une méthode sur la valeur renvoyée par l’appel précédent.
list.add("a").add("b") fonctionne lorsque le premier appel renvoie un objet doté de la méthode add suivante.
Chaînage optionnel
Le chaînage optionnel arrête un accès à une propriété, un accès par indice ou un appel lorsque la valeur vérifiée est null ou undefined, et donne undefined.
record.owner?.name permet l’absence de owner sans tenter de lire un nom depuis undefined.
Chaîne JSON
Une chaîne JSON est une donnée textuelle délimitée par des guillemets doubles, avec des séquences d’échappement pour des caractères comme les guillemets et les sauts de ligne.
Une valeur textuelle contenant un guillemet nécessite une séquence d’échappement à l’intérieur des guillemets doubles JSON qui l’entourent.
Clé d’indice de tableau
Une clé d’indice de tableau est une chaîne d’entier standard de 0 à 4 294 967 294, classée par ordre numérique avant les autres clés propres qui sont des chaînes.
La clé "3" est classée avant "12" dans Object.keys ; "03" reste parmi les clés de chaîne ordinaires.
Coalescence des nuls
La coalescence des nuls fournit une solution de repli uniquement lorsque son opérande de gauche est null ou undefined, et préserve les autres valeurs fausses.
settings.volume ?? 1 conserve un volume explicitement égal à zéro, tandis que settings.volume || 1 le remplace.
Copie profonde
Une copie profonde crée des données imbriquées indépendantes ainsi qu’une nouvelle valeur extérieure, sous réserve des types pris en charge par la méthode de copie.
Après un clonage pris en charge par structuredClone, modifier un champ imbriqué copié laisse le champ d’origine inchangé.
Copie superficielle
Une copie superficielle crée un nouvel objet ou tableau extérieur tout en conservant les références aux objets imbriqués qu’il contient.
Mettre à jour l’adresse imbriquée d’un enregistrement copié peut aussi modifier l’adresse partagée de l’enregistrement d’origine.

D

Décomposition d’itérable
La décomposition d’itérable développe un itérable en éléments de tableau ou en arguments d’appel distincts, en lisant ses valeurs dans l’ordre.
Math.max(...measurements) fournit chaque élément du tableau comme argument distinct à la fonction.
Décomposition d’objet
La décomposition d’objet copie les propriétés propres énumérables dans un nouveau littéral ; les occurrences ultérieures remplacent les valeurs précédentes d’une même clé.
{ ...base, active: true } copie base puis fournit la valeur finale de active.
Déstructuration d’objet
La déstructuration d’objet lit certaines propriétés dans des variables en faisant correspondre leurs noms.
const { city, tempC } = reading; crée deux variables locales à partir d’un relevé météorologique.
Déstructuration de tableau
La déstructuration de tableau lit les valeurs des positions successives d’un itérable dans un motif entre crochets.
const [low, high] = bounds; suppose que bounds place sa valeur inférieure avant sa valeur supérieure.
Différence
Une différence contient les valeurs d’une première collection qui sont absentes d’une seconde ; échanger les collections peut donc changer le résultat.
active.difference(blocked) conserve les valeurs actives qui ne figurent pas dans le Set des valeurs bloquées.
Différence symétrique
Une différence symétrique contient les valeurs présentes dans exactement une des deux collections et exclut toutes celles qu’elles partagent.
Comparer ainsi deux Set d’étiquettes permet de trouver celles qui appartiennent à une seule des deux listes.
Données imbriquées
Les données imbriquées placent des objets ou des tableaux dans d’autres objets ou tableaux : un chemin doit donc suivre plusieurs étapes pour atteindre une valeur.
report.readings[0].tempC lit une liste, son premier enregistrement, puis un champ de température.

E

Entier sûr
Un entier sûr est un entier de -9 007 199 254 740 991 à 9 007 199 254 740 991, intervalle dans lequel le type Number de JavaScript garde chaque entier distinct et exact.
Un identifiant qui dépasse l’intervalle sûr peut être envoyé sous forme de chaîne JSON afin de préserver chaque chiffre.
Entrée de Map
Une entrée de Map associe une clé à une valeur et se gère avec les méthodes de Map, indépendamment des propriétés d’objet ordinaires.
stock.set("tea", 4) modifie une entrée ; stock["tea"] = 4 modifie une propriété ordinaire.
Existence d’une propriété
L’existence d’une propriété signifie qu’une clé est présente, indépendamment du fait que sa valeur stockée soit vraie, fausse ou undefined.
Un enregistrement contenant 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
Un élément du reste dans une déstructuration de tableau regroupe les valeurs restantes dans un nouveau tableau et doit terminer le motif.
const [leader, ...others] = names; sépare le premier nom d’un tableau contenant les noms restants.

F

Fonction de rappel reviver
Une fonction de rappel reviver est une fonction de rappel de JSON.parse qui transforme les valeurs après leurs enfants et utilise ses valeurs de retour pour les remplacer ou les supprimer.
Une fonction de rappel reviver peut restaurer un champ de date connu et renvoyer toutes les valeurs sans rapport inchangées.
Fonction fléchée enveloppante
Une fonction fléchée enveloppante est une fonction de rappel fléchée dont le corps effectue plus tard l’appel de méthode voulu, en gardant explicite l’objet receveur de cet appel.
Passer () => counter.tick() à map fait que chaque appel de la fonction de rappel invoque tick par l’intermédiaire de l’objet compteur.

G

globalThis
globalThis fournit un moyen standard de faire référence à l’objet global, utilisé par les fonctions classiques non strictes lors d’un appel simple.
L’objet global d’un navigateur est window, mais un appel simple de fonction en mode strict reçoit tout de même undefined comme this.

I

Identité d’un objet
L’identité d’un objet est ce qui distingue un objet particulier de tous les autres, même lorsque les valeurs de leurs champs correspondent.
Deux enregistrements créés séparément avec id: 9 sont comparés comme différents avec === malgré leurs données identiques.
Intersection
Une intersection ne contient que les valeurs présentes dans les deux collections et exclut celles qui ne figurent que dans une seule.
L’intersection des identifiants actifs et des identifiants approuvés trouve ceux qui satisfont aux deux conditions d’appartenance.
Itérable
Un itérable fournit une séquence de valeurs à des opérations comme for...of ou la décomposition dans un tableau.
Les tableaux, les chaînes de caractères, les Map et les Set peuvent être déstructurés de cette façon ; un enregistrement simple ne le peut pas.

J

JSON
JSON est un format texte indépendant des langages qui représente les objets, les tableaux, les chaînes de caractères, les nombres, les booléens et null selon une syntaxe stricte.
Le texte {"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é.
L’analyse d’un enregistrement dont count est le nombre 4 permet le calcul, tandis qu’un count entre guillemets reste une chaîne de caractères.
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
Un littéral d’objet crée directement un objet avec des accolades et des propriétés sous forme de paires clé-valeur.
const reading = { tempC: 22 }; crée un enregistrement contenant une mesure de température.

M

Map
Une Map est une collection d’entrées clé-valeur dont les clés peuvent être de tout type ; elle conserve l’ordre de première insertion des clés.
La clé numérique 5 et la clé qui est la chaîne "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.
Regrouper des enregistrements par objet responsable partagé permet de retrouver le groupe avec cette même référence au responsable.
Méthode
Une méthode est une propriété dont la valeur est une fonction appelée par l’intermédiaire d’un objet.
Appeler tracker.advance() exécute l’action de tracker, tandis que lire tracker.advance renvoie une fonction.
Méthode détachée
Une méthode détachée est une fonction lue depuis un objet puis transmise ou stockée sans conserver l’objet dans son expression d’appel ultérieure.
const read = sensor.read; conserve la fonction, mais read() ne fournit pas sensor comme objet receveur.
Méthode empruntée
Une méthode empruntée est une fonction classique prise dans un autre objet et utilisée par l’intermédiaire d’un nouvel objet receveur sans modifier la fonction elle-même.
L’affectation b.read = a.read permet à b.read() d’utiliser les données de b lorsque la fonction lit par this.
Mise à jour immuable
Une mise à jour immuable construit de nouveaux contenants pour les données qui changent tout en préservant les contenants d’origine et les éventuelles valeurs partagées inchangées.
Une fonction de rappel de map peut renvoyer une copie par décomposition pour l’enregistrement modifié et réutiliser chaque enregistrement inchangé.
Motif de renommage
Un motif de renommage lit une propriété dans une variable locale de nom différent à l’aide de deux-points.
const { title: label } = page; crée label sans déclarer de variable appelée title.
Motif imbriqué
Un motif imbriqué sélectionne des valeurs dans une structure intérieure pendant la déstructuration de sa structure extérieure.
const { owner: { name } } = item; nécessite un objet owner et ne déclare que name.

N

Nom de propriété calculé
Un nom de propriété calculé évalue une expression entre crochets pour nommer une propriété dans un littéral.
Avec const code = "es";, { [code]: "Hola" } crée une propriété nommée "es".
Notation abrégée de méthode
La notation abrégée de méthode définit une méthode classique directement par son nom, ses paramètres et son corps dans un littéral.
Le membre reset() { this.n = 0; } définit une action sans deux-points distincts ni mot-clé function.
Notation entre crochets
La notation entre crochets évalue l’expression entre crochets pour sélectionner une clé de propriété.
Avec const field = "heightM";, person[field] sélectionne la mesure de taille de la personne.
Notation pointée
La notation pointée sélectionne le nom littéral de propriété situé après un point.
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.
Dans du code strict, affecter une valeur à la propriété status de niveau supérieur d’un enregistrement gelé lève une TypeError.
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.
Transformer la valeur de chaque paire puis reconstruire l’objet permet de convertir tout un enregistrement de mesures.
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.
Regrouper des tâches par état donne un tableau pour les tâches terminées et un autre pour les tâches en attente.
Objet d’options
Un objet d’options transmet des paramètres nommés à une fonction au lieu de dépendre des positions des arguments.
Une fonction qui reçoit { color, size } permet aux appelants d’indiquer le sens de chaque paramètre sans dépendre de leur ordre.
Objet receveur
Un objet receveur est l’objet fourni comme this lors de l’appel d’une méthode classique.
Dans account.describe(), account est l’objet receveur que la méthode utilise pour lire ses champs.
Ordre d’insertion
L’ordre d’insertion est l’ordre dans lequel des clés ou des valeurs distinctes entrent pour la première fois dans une collection ; l’itération des Map et des Set le conserve.
Mettre à jour une entrée de Map conserve sa place ; la supprimer puis insérer à nouveau sa clé la place en dernier.

P

Paire clé-valeur
Une paire clé-valeur est une séquence de deux éléments dont la première valeur est une clé de propriété ou de collection et la seconde, la donnée associée.
Object.entries({ lake: 5 }) produit [["lake", 5]], prêt à être parcouru dans une boucle utilisant la clé et la valeur.
Paramètre du reste
Un paramètre du reste regroupe les arguments restants d’une fonction dans un véritable tableau et doit être le dernier paramètre de la déclaration.
function total(...values) peut utiliser reduce sur values même lorsque l’appel ne fournit aucun argument.
Paramètre replacer
Un paramètre replacer est le deuxième argument de stringify : un tableau de noms de propriétés à inclure ou une fonction qui transforme les valeurs parcourues.
Renvoyer undefined pour une propriété privée d’un objet l’omet, tandis que renvoyer la valeur d’origine conserve les autres données.
Position ignorée
Une position ignorée consomme une valeur sans lui donner de nom dans un motif de déstructuration de tableau.
const [, second] = colors; ignore la première couleur et ne nomme que la valeur suivante fournie.
Propriété
Une propriété associe une clé d’objet à une valeur, qui peut être une donnée ou une fonction.
La propriété active dans { active: false } existe même si sa valeur est un booléen faux.
Propriété en notation abrégée
Une propriété en notation abrégée prend son nom et sa valeur d’une variable de même nom.
Avec une variable appelée city, le littéral { city } crée le même champ que { city: city }.
Propriété propre
Une propriété propre appartient directement à un objet : une vérification des propriétés propres n’inclut donc pas celles obtenues par héritage.
Object.hasOwn({}, "toString") est faux même si "toString" in {} est vrai.

R

Référence
Une référence relie une variable ou une propriété à un objet, permettant à plusieurs noms d’atteindre et de modifier la même valeur sous-jacente.
L’affectation const backup = record; donne un autre moyen d’accéder à record sans copier ses champs.
Référence circulaire
Une référence circulaire est un chemin de références entre objets qui revient à un objet déjà présent sur ce chemin, ce que JSON ordinaire ne peut pas encoder.
Ajouter record.self = record fait lever une TypeError à JSON.stringify ordinaire pour cet enregistrement.
Reste d’objet
Le reste d’objet regroupe dans un nouvel objet superficiel les propriétés propres énumérables qui ne sont pas déjà nommées dans un motif de déstructuration.
const { password, ...publicRecord } = user; laisse user intact tout en excluant password de la copie.

S

Séquence d’échappement
Une séquence d’échappement utilise une barre oblique inverse et les caractères qui la suivent pour représenter un caractère spécial ou une unité de code UTF-16 dans une chaîne JSON.
Convertir en chaîne un message contenant une nouvelle ligne écrit une séquence d’échappement au lieu de placer un saut de ligne brut dans la chaîne.
Sérialisation
La sérialisation convertit des valeurs en mémoire en une représentation qui peut être stockée ou échangée, comme le texte JSON produit par stringify.
Un objet de paramètres doit être sérialisé pour qu’une destination qui n’accepte que du texte puisse recevoir sa structure.
Set
Un Set est une collection de valeurs uniques de tout type qui conserve l’ordre d’insertion pour l’itération et ne possède pas de positions indexées.
Ajouter "ready" deux fois ne conserve qu’une valeur, tandis qu’ajouter deux enregistrements distincts aux champs identiques conserve les deux.
Sous-ensemble
Un sous-ensemble est une collection dont chaque valeur appartient aussi à une autre collection, y compris lorsque les deux collections sont égales.
Un Set d’autorisations requises n’est un sous-ensemble des autorisations accordées que si chaque valeur requise est accordée.
structuredClone
structuredClone copie les valeurs JavaScript imbriquées prises en charge, y compris les structures circulaires, mais rejette les valeurs qui sont des fonctions.
Un enregistrement contenant des tableaux simples peut être cloné ; y inclure une méthode provoque une DataCloneError.
SyntaxError
Une SyntaxError signale une syntaxe invalide, comme un texte mal formé fourni à JSON.parse.
Une virgule finale dans du JSON externe peut être interceptée avec try...catch afin que le programme puisse gérer l’erreur.

T

Test d’appartenance
Un test d’appartenance vérifie si une clé ou une valeur est présente dans une collection, indépendamment des données stockées sous cette clé.
map.has(key) peut trouver une entrée existante même lorsque map.get(key) renvoie undefined.
this
Le mot-clé this désigne le contexte actuel d’une fonction ; les fonctions classiques le reçoivent généralement de l’appel et les fonctions fléchées conservent un contexte extérieur.
Une même méthode de lecture classique non liée peut lire différents objets lorsqu’elle est appelée par l’intermédiaire de différents objets receveurs.
this lexical
Le this lexical est la valeur this environnante conservée par une fonction fléchée à l’endroit où elle est créée, sans qu’un objet receveur ou une liaison ultérieurs puissent la modifier.
Une fonction fléchée créée dans une méthode en cours d’exécution peut conserver l’objet de cette méthode pendant une fonction de rappel de tableau.
toJSON
Une méthode toJSON renvoie la représentation compatible avec JSON choisie pour un objet, que stringify écrit à la place de l’objet d’origine.
Un objet de mesure peut renvoyer un enregistrement simple plus réduit contenant les champs destinés à l’échange.

U

Union
Une union contient chaque valeur présente dans l’une ou l’autre de deux collections ; les valeurs communes ne figurent qu’une fois dans le Set obtenu.
Si un groupe contient Ana et Bo et un autre Bo et Cai, leur union contient les trois personnes.

V

Valeur dérivée
Une valeur dérivée est calculée à partir d’autres données stockées, comme un total à partir de lignes d’articles, et peut devenir périmée si elle est stockée séparément.
Calculer la distance d’un trajet à partir de ses étapes maintient la cohérence du résultat après la modification d’une étape.
Valeur par défaut de déstructuration
Une valeur par défaut de déstructuration remplace une valeur sélectionnée égale à undefined, notamment pour un champ ou une position absente.
Dans const { count = 2 } = { count: null };, le null explicite est conservé malgré la valeur par défaut.
Vérification de structure
Une vérification de structure contrôle qu’une valeur analysée possède les champs, les types de contenants et les types de valeurs dont le programme a besoin avant de l’utiliser.
Un JSON valide contenant un compte sous forme de chaîne doit encore être vérifié avant qu’un programme traite ce champ comme un nombre.

W

WeakMap
Une WeakMap associe des valeurs à des clés qui sont des objets ou des symboles non enregistrés, sans maintenir en mémoire les clés qui seraient autrement inaccessibles.
Une WeakMap peut associer des métadonnées à un objet sans lui ajouter de champs ni exposer de liste d’entrées.
WeakSet
Un WeakSet enregistre l’appartenance d’objets ou de symboles non enregistrés sans maintenir en mémoire les membres qui seraient autrement inaccessibles et ne peut pas être parcouru par itération.
Un WeakSet peut marquer des objets traités sans les conserver uniquement parce qu’ils ont été traités.

À propos de cette unité

Par StudeliSignaler une erreur

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.

Commencer