0%
JavaScript Moderne : Map et Set

Map et Set

Collections de Données Modernes

10-15 min

JavaScript Moderne : Map, Set et les nouvelles structures de données

Les structures de données Map et Set, introduites avec ES6, offrent de nouvelles façons puissantes de gérer les collections de données en JavaScript.

Map

Map est une collection de paires clé-valeur où les clés peuvent être de n’importe quel type.

Création et manipulation de base

// 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();

Initialisation avec un tableau

const contacts = new Map([
    ['alice', '0123456789'],
    ['bob', '9876543210']
]);

// Itération sur les entrées
for (const [nom, telephone] of contacts) {
    console.log(`${nom}: ${telephone}`);
}

Méthodes d’itération

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}`);
});

Cas d’utilisation avancés

// 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

Set est une collection de valeurs uniques de n’importe quel type.

Création et manipulation de base

// 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();

Initialisation avec un tableau

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];

Opérations sur les ensembles

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 et WeakSet

Ces versions “faibles” permettent la collecte automatique des éléments non référencés.

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;

Patterns et cas d’utilisation pratiques

Cache avec 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' });

Gestionnaire d’événements avec 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' });

Gestion de l’état avec 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"

Exercices pratiques

  1. Gestionnaire de tâches uniques
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"]
  1. Système de cache avec 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 et Set sont des structures de données essentielles en JavaScript moderne :

  • Map offre une alternative plus flexible aux objets pour les collections clé-valeur
  • Set simplifie la gestion des collections de valeurs uniques
  • WeakMap et WeakSet sont utiles pour la gestion de la mémoire
  • Ces structures facilitent l’implémentation de patterns courants comme le cache et la gestion d’événements

Dans le prochain tutoriel, nous mettrons en pratique toutes ces connaissances dans un projet complet d’application de notes.


Besoin de réviser les modules ES ? Consultez notre tutoriel précédent sur les modules.

Commentaires

Les commentaires sont alimentés par GitHub Discussions

Connectez-vous avec GitHub pour participer à la discussion

Lien copié !