Map and Set
Modern Data Collections
Modern JavaScript: Map, Set, and the New Data Structures
The Map and Set data structures, introduced with ES6, offer powerful new ways to manage data collections in JavaScript.
Map
A Map is a collection of key-value pairs where keys can be of any type.
Creation and basic manipulation
// Création d'une Map
const utilisateurs = new Map();
// Ajout d'éléments
utilisateurs.set('alice', { nom: 'Alice', age: 25 });
utilisateurs.set('bob', { nom: 'Bob', age: 30 });
// Récupération de valeurs
console.log(utilisateurs.get('alice')); // { nom: 'Alice', age: 25 }
// Vérification d'existence
console.log(utilisateurs.has('bob')); // true
// Suppression d'éléments
utilisateurs.delete('bob');
// Taille de la Map
console.log(utilisateurs.size); // 1
// Vider la Map
utilisateurs.clear();
Initialization with an array
const contacts = new Map([
['alice', '0123456789'],
['bob', '9876543210']
]);
// Itération sur les entrées
for (const [nom, telephone] of contacts) {
console.log(`${nom}: ${telephone}`);
}
Iteration methods
const scores = new Map([
['Alice', 95],
['Bob', 80],
['Charlie', 85]
]);
// Itération sur les clés
for (const nom of scores.keys()) {
console.log(nom);
}
// Itération sur les valeurs
for (const score of scores.values()) {
console.log(score);
}
// Itération sur les entrées
scores.forEach((score, nom) => {
console.log(`${nom}: ${score}`);
});
Advanced use cases
// Utilisation d'objets comme clés
const objetA = { id: 1 };
const objetB = { id: 2 };
const donnees = new Map();
donnees.set(objetA, 'Données pour A');
donnees.set(objetB, 'Données pour B');
console.log(donnees.get(objetA)); // "Données pour A"
// Conversion Map vers Object
const mapVersObjet = Object.fromEntries(scores);
// Conversion Object vers Map
const objet = { a: 1, b: 2 };
const objetVersMap = new Map(Object.entries(objet));
Set
A Set is a collection of unique values of any type.
Creation and basic manipulation
// Création d'un Set
const nombres = new Set();
// Ajout d'éléments
nombres.add(1);
nombres.add(2);
nombres.add(2); // Ignoré car déjà présent
console.log(nombres.size); // 2
// Vérification d'existence
console.log(nombres.has(1)); // true
// Suppression d'éléments
nombres.delete(1);
// Vider le Set
nombres.clear();
Initialization with an array
const fruits = new Set(['pomme', 'banane', 'pomme', 'orange']);
console.log(fruits.size); // 3 (pomme n'est compté qu'une fois)
// Conversion Set vers Array
const fruitsUniques = [...fruits];
Set operations
function intersection(setA, setB) {
return new Set([...setA].filter(x => setB.has(x)));
}
function union(setA, setB) {
return new Set([...setA, ...setB]);
}
function difference(setA, setB) {
return new Set([...setA].filter(x => !setB.has(x)));
}
// Exemple d'utilisation
const setA = new Set([1, 2, 3, 4]);
const setB = new Set([3, 4, 5, 6]);
console.log(intersection(setA, setB)); // Set(2) {3, 4}
console.log(union(setA, setB)); // Set(6) {1, 2, 3, 4, 5, 6}
console.log(difference(setA, setB)); // Set(2) {1, 2}
WeakMap and WeakSet
These “weak” versions allow unreferenced elements to be garbage collected automatically.
WeakMap
// Création d'une WeakMap
const cache = new WeakMap();
let objet = { id: 1 };
cache.set(objet, 'données associées');
// Si objet est mis à null, les données seront nettoyées
objet = null;
WeakSet
const abonnes = new WeakSet();
let utilisateur = { nom: 'Alice' };
abonnes.add(utilisateur);
console.log(abonnes.has(utilisateur)); // true
// Si utilisateur est mis à null, il sera automatiquement retiré
utilisateur = null;
Practical Patterns and Use Cases
Cache with Map
class Cache {
constructor(ttl = 3600000) { // TTL par défaut : 1 heure
this.cache = new Map();
this.ttl = ttl;
}
set(key, value) {
this.cache.set(key, {
value,
timestamp: Date.now()
});
}
get(key) {
const item = this.cache.get(key);
if (!item) return null;
if (Date.now() - item.timestamp > this.ttl) {
this.cache.delete(key);
return null;
}
return item.value;
}
clear() {
this.cache.clear();
}
}
// Utilisation
const cache = new Cache(5000); // TTL de 5 secondes
cache.set('utilisateur', { id: 1, nom: 'Alice' });
Event handler with Set
class EventEmitter {
constructor() {
this.listeners = new Map();
}
on(event, callback) {
if (!this.listeners.has(event)) {
this.listeners.set(event, new Set());
}
this.listeners.get(event).add(callback);
}
off(event, callback) {
if (this.listeners.has(event)) {
this.listeners.get(event).delete(callback);
}
}
emit(event, data) {
if (this.listeners.has(event)) {
for (const callback of this.listeners.get(event)) {
callback(data);
}
}
}
}
// Utilisation
const emitter = new EventEmitter();
const handler = data => console.log('Données reçues:', data);
emitter.on('data', handler);
emitter.emit('data', { message: 'Hello' });
State management with Map
class Store {
constructor() {
this.state = new Map();
this.subscribers = new Map();
}
setState(key, value) {
this.state.set(key, value);
if (this.subscribers.has(key)) {
this.subscribers.get(key).forEach(callback =>
callback(value)
);
}
}
getState(key) {
return this.state.get(key);
}
subscribe(key, callback) {
if (!this.subscribers.has(key)) {
this.subscribers.set(key, new Set());
}
this.subscribers.get(key).add(callback);
return () => this.subscribers.get(key).delete(callback);
}
}
// Utilisation
const store = new Store();
const unsubscribe = store.subscribe('compteur', value =>
console.log('Nouveau compteur:', value)
);
store.setState('compteur', 1); // Affiche "Nouveau compteur: 1"
Practice Exercises
- Unique task manager
class GestionnaireTaches {
constructor() {
this.taches = new Set();
}
ajouterTache(tache) {
if (this.taches.has(tache)) {
return false;
}
this.taches.add(tache);
return true;
}
supprimerTache(tache) {
return this.taches.delete(tache);
}
getTaches() {
return [...this.taches];
}
}
// Utilisation
const gestionnaire = new GestionnaireTaches();
gestionnaire.ajouterTache('Apprendre JavaScript');
gestionnaire.ajouterTache('Apprendre JavaScript'); // Retourne false
console.log(gestionnaire.getTaches()); // ["Apprendre JavaScript"]
- Cache system with expiration
class CacheAvecExpiration {
constructor() {
this.cache = new Map();
}
set(key, value, ttl) {
const expiration = Date.now() + ttl;
this.cache.set(key, { value, expiration });
}
get(key) {
const item = this.cache.get(key);
if (!item) return null;
if (Date.now() > item.expiration) {
this.cache.delete(key);
return null;
}
return item.value;
}
nettoyer() {
const maintenant = Date.now();
for (const [key, item] of this.cache) {
if (maintenant > item.expiration) {
this.cache.delete(key);
}
}
}
}
// Utilisation
const cache = new CacheAvecExpiration();
cache.set('api-data', { results: [] }, 5000); // Expire après 5 secondes
Conclusion
Map and Set are essential data structures in modern JavaScript:
- Map offers a more flexible alternative to objects for key-value collections
- Set simplifies the management of collections of unique values
- WeakMap and WeakSet are useful for memory management
- These structures make it easier to implement common patterns such as caching and event handling
In the next tutorial, we’ll put all of this knowledge into practice in a complete notes application project.
Need to review ES modules? Check out our previous tutorial on modules.
Comments
Comments are powered by GitHub Discussions
Sign in with GitHub to join the discussion