Quand une application doit associer un identifiant à une valeur, par exemple un produit à son prix ou un utilisateur à ses permissions, le choix de la bonne structure JavaScript évite bien des complications. Un dictionnaire JavaScript peut prendre la forme d’un objet, d’une instance de Map ou, dans des cas plus particuliers, d’un WeakMap. Je présente ici leurs différences, leurs méthodes essentielles, leurs limites et les situations où chacune devient réellement utile.
Les repères essentiels pour choisir une structure clé-valeur
- Objet : adapté aux données connues à l’avance, comme une configuration ou un profil.
- Map : préférable pour une collection dynamique avec ajout, suppression et recherche fréquents.
- Clés flexibles : une Map accepte des chaînes, nombres, objets, fonctions et autres valeurs.
-
Itération : Map conserve explicitement l’ordre d’insertion et se parcourt directement avec
for...of. - Sérialisation : un objet passe naturellement dans JSON, tandis qu’une Map demande une conversion.
Un objet JavaScript suffit souvent pour commencer
La manière la plus simple d’associer des clés et des valeurs consiste à utiliser un objet littéral. C’est le bon choix lorsque les propriétés représentent la structure même d’une donnée, avec des noms relativement stables.
const utilisateur = {
nom: "Claire",
role: "administratrice",
actif: true
};
console.log(utilisateur.nom);
console.log(utilisateur["role"]);
La notation avec un point est agréable lorsque la clé est connue dans le code. Les crochets deviennent indispensables pour une clé stockée dans une variable, contenant des espaces ou générée dynamiquement.
const langue = "français";
const profil = {};
profil[langue] = "fr-FR";
console.log(profil[langue]);
Je privilégie les objets pour les enregistrements structurés : réponses d’API, options d’un composant, données de formulaire ou paramètres d’une fonction. Ils sont aussi faciles à inspecter et compatibles avec JSON.stringify(), ce qui simplifie les échanges avec un serveur.
Il faut toutefois garder une limite en tête. Les clés ordinaires d’un objet sont essentiellement des chaînes de caractères ou des symboles. Si vous utilisez un nombre comme clé, JavaScript le convertit généralement en chaîne. Un objet possède également un prototype, ce qui peut créer des collisions avec des propriétés héritées lorsque les clés viennent d’une source non fiable.
Pourquoi Map est souvent le vrai dictionnaire dynamique
Map a été conçue pour gérer une collection de paires clé-valeur. Elle est particulièrement confortable lorsque les entrées apparaissent et disparaissent pendant l’exécution, comme dans un cache, une table de sessions ou un index de résultats.
const prix = new Map();
prix.set("ordinateur", 899);
prix.set("clavier", 79);
console.log(prix.get("ordinateur"));
console.log(prix.has("clavier"));
prix.delete("clavier");
console.log(prix.size);
Les méthodes principales sont faciles à retenir : set() ajoute ou remplace une valeur, get() la récupère, has() vérifie la présence d’une clé, delete() supprime une entrée et clear() vide toute la collection. La propriété size donne directement le nombre d’éléments.
La différence la plus intéressante concerne les clés. Une Map peut utiliser n’importe quelle valeur JavaScript, y compris un objet ou une fonction.
const permissions = new Map();
const compte = { id: 42 };
permissions.set(compte, ["lecture", "écriture"]);
console.log(permissions.get(compte));
Attention, deux objets qui contiennent les mêmes propriétés ne sont pas pour autant la même clé. JavaScript compare ici les références, pas le contenu. Il faut donc réutiliser exactement la même référence pour retrouver la valeur enregistrée.
Objet ou Map selon le besoin réel
Je ne recommande pas de remplacer systématiquement les objets par des Map. Le meilleur choix dépend de la nature des données, de la manière dont elles sont modifiées et de leur destination finale.
| Critère | Objet | Map |
|---|---|---|
| Type de clé | Chaîne ou symbole | Tout type de valeur |
| Nombre d’entrées | Object.keys(obj).length |
map.size |
| Parcours | Object.entries() |
for...of directement |
| JSON | Compatible nativement | Conversion nécessaire |
| Usage typique | Enregistrement de données | Collection dynamique |
Pour une structure de configuration, je choisis donc généralement l’objet. Pour un cache dont les entrées changent régulièrement, je préfère Map, car son API exprime clairement l’intention et évite de mélanger propriétés métier et méthodes héritées.
Une Map conserve aussi l’ordre d’insertion, ce qui rend son parcours prévisible. Les objets suivent eux aussi des règles d’énumération, mais leur comportement est moins explicite et certaines clés numériques peuvent apparaître dans un ordre particulier. Ce détail compte pour les menus, historiques, files d’attente légères et résultats affichés dans l’interface.

Parcourir, transformer et convertir les données
Une Map se parcourt naturellement avec for...of. Chaque élément fournit un tableau composé de la clé puis de la valeur.
const scores = new Map([
["Alice", 18],
["Benoît", 15],
["Chloé", 20]
]);
for (const [nom, score] of scores) {
console.log(`${nom} : ${score}`);
}
Les méthodes keys(), values() et entries() permettent de cibler une partie de la collection. forEach() existe également, mais je trouve souvent la boucle for...of plus lisible dès qu’il faut ajouter une condition ou plusieurs instructions.
Pour un objet, les outils équivalents sont Object.keys(), Object.values() et Object.entries(). Cette dernière méthode permet de réutiliser une logique proche de celle d’une Map.
const configuration = {
thème: "sombre",
notifications: true
};
for (const [clé, valeur] of Object.entries(configuration)) {
console.log(clé, valeur);
}
La conversion entre les deux structures est simple, mais elle doit rester explicite. Une Map peut devenir un objet avec Object.fromEntries() si ses clés sont compatibles avec des propriétés d’objet.
const map = new Map([
["port", 3000],
["mode", "production"]
]);
const objet = Object.fromEntries(map);
const texte = JSON.stringify(objet);
console.log(texte);
Dans l’autre sens, new Map(Object.entries(objet)) fonctionne très bien. Ce passage modifie toutefois la nature des clés et ne préserve pas les clés objet originales. Pour stocker une Map dans une API JSON, je transforme donc volontairement ses entrées plutôt que de compter sur une conversion automatique.
Les erreurs qui rendent ces structures difficiles à maintenir
Confondre Map et la méthode map()
Map est une structure de données, alors que map() est une méthode des tableaux qui produit un nouveau tableau après transformation. Le nom est proche, mais le rôle est totalement différent. Une Map ne se parcourt pas avec tableau.map().
Tester une valeur au lieu de tester une clé
Ce code peut être trompeur si une valeur valide vaut undefined :
if (dictionnaire.get("statut") !== undefined) {
console.log("Clé trouvée");
}
La méthode recommandée est has() pour vérifier l’existence, puis get() pour lire la valeur. Cette distinction devient importante dans les caches et les résultats d’API, où null et undefined peuvent avoir une signification métier.
Utiliser un objet avec des clés non fiables
Lorsque les clés viennent d’un formulaire, d’un fichier ou d’une requête externe, un objet classique mérite davantage de précautions. Une Map réduit les risques liés aux propriétés héritées. Pour un dictionnaire objet volontairement dépourvu de prototype, on peut aussi utiliser Object.create(null), mais cette solution demande plus de rigueur et ne fournit pas les méthodes habituelles d’un objet.
Lire aussi : Formation WordPress gratuite - Le guide complet pour débuter
Mesurer la performance sans scénario réel
On entend souvent qu’une Map serait toujours plus rapide. Cette affirmation est trop simpliste. Les performances dépendent du moteur JavaScript, du volume de données, du nombre d’accès et des opérations réalisées. Pour une dizaine de propriétés fixes, la lisibilité d’un objet compte davantage qu’une différence théorique. Pour des milliers d’entrées manipulées fréquemment, un test dans votre application reste le meilleur arbitre.
WeakMap pour associer des métadonnées sans retenir les objets
WeakMap répond à un besoin plus spécialisé. Ses clés doivent être des objets ou certains symboles, et la collection ne les empêche pas d’être supprimés automatiquement par le ramasse-miettes lorsqu’aucune autre référence ne subsiste.
const metadonnees = new WeakMap();
const bouton = document.querySelector("button");
metadonnees.set(bouton, {
dernierClic: Date.now()
});
console.log(metadonnees.get(bouton));
Cette structure convient pour stocker des informations privées liées au cycle de vie d’un objet, par exemple l’état interne d’un composant DOM ou des données utilisées par une bibliothèque. En revanche, WeakMap ne propose pas de parcours global ni de propriété size. Si vous devez afficher toutes les entrées, il faut utiliser Map ou un objet.
Dans une application web, mon approche est assez pragmatique. Je commence par un objet pour une donnée descriptive, je passe à Map lorsque la collection devient dynamique ou utilise des clés complexes, et je réserve WeakMap aux métadonnées qui ne doivent pas prolonger artificiellement la durée de vie d’un objet.
Le bon réflexe pour un code JavaScript durable
Le mot « dictionnaire » décrit surtout une intention, pas un type unique du langage. La question utile n’est pas de savoir quelle structure est la plus moderne, mais si les clés sont connues, si les données doivent être sérialisées et si la collection évolue fortement pendant l’exécution.
- Choisissez un objet pour une donnée structurée et facilement convertie en JSON.
- Choisissez Map pour des entrées dynamiques, des clés de tout type et un parcours explicite.
- Choisissez WeakMap pour des métadonnées attachées à des objets sans gérer manuellement leur nettoyage.
Ce choix simple améliore souvent la lisibilité avant même d’avoir un effet mesurable sur les performances. En JavaScript, une structure adaptée rend le code plus prévisible, limite les erreurs de clé et clarifie immédiatement la façon dont les données doivent vivre dans l’application.