Question 1Avec const ids = new Set(["u-1", "u-2"]);, exécute ids.add("u-1");. Que vaut ids.size ?
Map et Set — retirer les doublons et des comptes indexés
Set ne garde chaque valeur qu'une fois, Map garde des paires clé-valeur dans l'ordre d'ajout.
Rassemble dans un tableau les tags attachés à un produit, et le même tag revient sans cesse — pour savoir combien il y en a réellement de différents, il faut vérifier avec includes à chaque fois. Vouloir garder une paire clé-valeur, comme un compte de stock indexé par ID produit, se heurte au même mur avec de simples tableaux : il faudrait deux tableaux séparés pour les ID et les quantités, alignés par position, et les clés d'un objet sont limitées aux chaînes et aux symbol, donc un nombre ne peut pas servir de clé tel quel.
Cet article couvre Set, qui ne garde jamais de doublons, et Map, qui peut utiliser autre chose que des chaînes comme clés.
Retirer les doublons — construire un Set
Imagine que tu veuilles savoir combien de tags distincts sont réellement utilisés sur une liste de produits tagués. Dans un simple tableau, le même tag apparaît plusieurs fois, donc le compter tel quel gonfle le total. Il te faut une structure de données qui garde les doublons retirés dès le départ.
Un Set (une structure de données qui garde chaque valeur une seule fois) se construit en passant un tableau, comme dans new Set(tags). Le new en tête est une syntaxe que tu mets avant de créer une nouvelle instance d'un type fixe de structure de données, comme Set ou Map.
Comme la même valeur n'ajoute jamais de doublon, lire size seul te donne le nombre de valeurs distinctes. Si deux valeurs comptent comme identiques suit la même règle que ===.
Un Set n'est pas un tableau, donc un index comme uniqueTags[0] ne renverra rien. Quand tu as besoin de lui comme tableau, convertis-le avec la syntaxe spread, comme dans [...uniqueTags].
L'ordre reste exactement celui dans lequel les éléments ont été ajoutés en premier, donc l'ordre d'apparition du tableau original se retrouve inchangé.
const tags = ["Solde", "Nouveauté", "Solde", "Livraison gratuite"];
// Passe un tableau, et tu obtiens un Set sans doublons
const uniqueTags = new Set(tags);
console.log(uniqueTags.size); // 3
// Reconvertis en tableau avec la syntaxe spread (ordre d'ajout préservé)
console.log([...uniqueTags].join(", ")); // Solde, Nouveauté, Livraison gratuite
// Le tableau original est intact
console.log(tags.length); // 4
// Tu peux aussi partir d'un Set vide
const empty = new Set();
console.log(empty.size); // 0
Ajouter et supprimer des valeurs — add, has, et delete
Parfois tu veux logger des ID de visiteurs et compter la même personne comme 1 peu importe combien de fois elle revient. Garde ça dans un tableau, et chaque ajout veut dire vérifier avec includes avant push — plus les enregistrements s'accumulent, plus cette vérification prend de temps.
Un Set a add pour ajouter une valeur, has pour vérifier s'il en a une, delete pour en retirer une, et size pour le compte. add ne fait rien quand la même valeur arrive, donc tu n'as jamais besoin de vérifier avant d'ajouter.
has renvoie true ou false, et delete renvoie s'il a réellement retiré quelque chose.
adder la même valeur autant de fois que tu veux n'augmente jamais le compte. Seul retirer le fait diminuer.const visitors = new Set(["u-102", "u-337"]);
// Vérifie s'il en a une
console.log(visitors.has("u-102")); // true
console.log(visitors.has("u-999")); // false
// Ajoutes-en une. La même valeur ne change pas le compte
visitors.add("u-541");
console.log(visitors.size); // 3
visitors.add("u-541");
console.log(visitors.size); // 3
// Retire-en une. Si ça a réellement retiré quelque chose revient
console.log(visitors.delete("u-102")); // true
console.log(visitors.delete("u-102")); // false (déjà partie)
console.log(visitors.size); // 2
Garder des paires clé-valeur — Map
Parfois tu veux garder une clé et une valeur comme une paire, comme un compte de stock indexé par ID produit. Un objet peut faire ça aussi, mais pour comptabiliser des clés décidées à l'exécution — comme des ID — et les ajuster au fil du temps, une structure de données avec des méthodes dédiées convient mieux.
Un Map (une structure de données qui garde des paires clé-valeur dans l'ordre où elles ont été enregistrées) se construit avec new Map(), et tu enregistres des entrées avec set(key, value). Pour en lire une, utilise get(key) ; pour vérifier si elle existe, has(key) ; pour le compte, size.
set la même clé à nouveau, et la valeur se fait écraser. Pour commencer avec des entrées déjà remplies, passe un tableau de paires, comme dans new Map([["P-001", 12], ["P-002", 5]]).
set enregistre une paire, et get cherche une valeur par clé. Une clé sans entrée renvoie undefined.const stock = new Map();
// Enregistre une paire avec set
stock.set("P-001", 12);
stock.set("P-002", 5);
console.log(stock.size); // 2
// Cherche une valeur à partir d'une clé avec get
console.log(stock.get("P-002")); // 5
console.log(stock.get("P-999")); // undefined
console.log(stock.has("P-999")); // false
// set la même clé à nouveau, et ça écrase
stock.set("P-001", 8);
console.log(stock.get("P-001")); // 8
console.log(stock.size); // 2 (le compte n'augmente pas)
// Tu peux aussi le construire avec des paires déjà remplies
const prices = new Map([["P-001", 3980], ["P-002", 2480]]);
console.log(prices.get("P-001")); // 3980
Les valeurs d'un Map ne se lisent pas avec la notation pointée
Écris stock["P-001"] au lieu de stock.get("P-001"), et tu ne récupéreras pas la valeur. Cette syntaxe cherche une propriété sur l'objet Map lui-même, ce qui n'a rien à voir avec les paires que tu as enregistrées, donc ça renvoie undefined. Fais passer la lecture et l'écriture par get et set.
Choisir entre Map et Object — type de clé et ordre
Puisqu'il garde des clés et des valeurs tout comme un objet, tu choisis entre les deux. Quand les clés sont fixées au moment où tu écris le code, comme des champs de paramètres, un objet fonctionne ; quand tu comptabilises des clés qui grandissent à l'exécution, comme des ID ou des dates, Map est plus facile à manier.
Le type de clé et l'ordre sont sur quoi tu bases cette décision.
Les clés d'un objet se convertissent en chaînes, donc même écrire record[2026], la vraie clé est "2026". Un Map utilise exactement la valeur que tu passes comme clé telle quelle, donc le nombre 2026 et la chaîne "2026" sont traités comme des clés différentes.
L'ordre fonctionne différemment aussi — un Map garde toujours l'ordre d'enregistrement.
| Aspect | Object | Map |
|---|---|---|
| Types autorisés comme clés | Convertis en chaînes | N'importe quel type, gardé tel quel |
| Ordre | Les clés type entier trient en premier | Reste dans l'ordre d'enregistrement |
| Compter les entrées | length de Object.keys | size |
| Lire & écrire | obj.key / obj[key] | get et set |
| Convient le mieux à | Une collection fixe de champs | Comptabiliser des clés qui grandissent à l'exécution |
Pour lister le contenu d'un Map, écris [...stock.entries()] pour le convertir en un tableau de paires [clé, valeur], chacune un tableau à 2 éléments. Ça te permet d'extraire une paire à la fois, comme dans entries[0]. Répéter la même étape une fois par paire, quel que soit leur nombre, est couvert à nouveau dans l'article sur les boucles.
Quand tu as besoin de juste les clés, utilise stock.keys() — mais puisque ce que ça renvoie n'est pas un tableau, tu ne peux pas enchaîner join directement dessus. Écris [...stock.keys()] pour le convertir en tableau d'abord.
const scores = new Map([["math", 80]]);
// Un Map garde une clé nombre comme un nombre
scores.set(2026, "bilan de cette année");
console.log(scores.get(2026)); // bilan de cette année
console.log(scores.get("2026")); // undefined (une clé différente)
// Les clés d'un objet se convertissent en chaînes
const record = {};
record[2026] = "bilan de cette année";
console.log(Object.keys(record)[0]); // 2026
console.log(typeof Object.keys(record)[0]); // string
console.log(record["2026"]); // bilan de cette année (traité comme la même clé)
// Convertis keys() / entries() en tableau avec la syntaxe spread avant de les utiliser
console.log([...scores.keys()].join(", ")); // math, 2026
const pairs = [...scores.entries()];
console.log(pairs[0].join(": ")); // math: 80
// Un objet trie les clés type entier en premier
const ranking = {};
ranking[3] = "c";
ranking[1] = "a";
console.log(Object.keys(ranking).join(", ")); // 1, 3
Vérification des connaissances
Répondez à chaque question une par une.
Question 2Avec stock comme Map, que renvoie stock.get("P-999") pour une clé non enregistrée ?
Question 3Enregistre le nombre 2026 comme clé. Quelle est la différence entre Map et un objet ?