🚀 Nuova versione beta disponibile! Feedback o problemi? Contattaci

WeakMap in JavaScript

Codegrind TeamAug 23 2024

WeakMap è una struttura dati in JavaScript che permette di creare collezioni di coppie chiave-valore, dove le chiavi sono oggetti e i valori possono essere di qualsiasi tipo. La caratteristica distintiva di un WeakMap è che mantiene una “referenza debole” alle chiavi degli oggetti. Questo significa che se non ci sono altre referenze a un oggetto utilizzato come chiave, l’oggetto può essere garbage collected, liberando automaticamente la memoria associata. Questo rende i WeakMap particolarmente utili per scenari in cui è necessario associare dati a oggetti senza prevenire la loro rimozione automatica dalla memoria.

Cos’è un WeakMap?

Un WeakMap è simile a un normale Map, ma con alcune differenze chiave:

  1. Chiavi Oggetto: In un WeakMap, solo gli oggetti possono essere utilizzati come chiavi.
  2. Referenze Deboli: Le chiavi in un WeakMap non impediscono agli oggetti di essere garbage collected. Se l’unica referenza a un oggetto è una chiave in un WeakMap, l’oggetto può essere rimosso dalla memoria.
  3. Non Enumerabile: Gli elementi di un WeakMap non possono essere iterati o enumerati, rendendo il contenuto del WeakMap non accessibile direttamente.

Creazione di un WeakMap

Puoi creare un WeakMap utilizzando il costruttore WeakMap().

Esempio di Creazione

let weakmap = new WeakMap();

Puoi anche inizializzare un WeakMap con un array di coppie chiave-valore.

Esempio

let obj1 = { nome: "Mario" };
let obj2 = { nome: "Luigi" };

let weakmap = new WeakMap([
  [obj1, "Personaggio 1"],
  [obj2, "Personaggio 2"],
]);

console.log(weakmap.get(obj1)); // Output: "Personaggio 1"

Metodi Principali di un WeakMap

set()

Il metodo set() aggiunge o aggiorna una coppia chiave-valore nel WeakMap.

Sintassi

weakmap.set(chiave, valore);

Esempio

let obj = { id: 1 };
let weakmap = new WeakMap();
weakmap.set(obj, "Dato associato");
console.log(weakmap.get(obj)); // Output: "Dato associato"

get()

Il metodo get() restituisce il valore associato a una chiave nel WeakMap.

Sintassi

let valore = weakmap.get(chiave);

Esempio

console.log(weakmap.get(obj)); // Output: "Dato associato"

has()

Il metodo has() verifica se una chiave esiste nel WeakMap.

Sintassi

let esiste = weakmap.has(chiave);

Esempio

console.log(weakmap.has(obj)); // Output: true

delete()

Il metodo delete() rimuove una coppia chiave-valore dal WeakMap.

Sintassi

weakmap.delete(chiave);

Esempio

weakmap.delete(obj);
console.log(weakmap.has(obj)); // Output: false

Caratteristiche e Limitazioni di WeakMap

1. Garbage Collection Automatica

Il vantaggio principale di un WeakMap è che permette di creare associazioni tra oggetti senza interferire con il garbage collection. Questo è utile in scenari dove i dati associati a un oggetto non dovrebbero prevenire la rimozione dell’oggetto dalla memoria.

Esempio

let oggetto = { nome: "Mario" };
let weakmap = new WeakMap();
weakmap.set(oggetto, "Dato importante");

// Se "oggetto" non è più referenziato altrove, sarà garbage collected, e il suo valore in WeakMap sarà rimosso automaticamente.
oggetto = null;

2. Non Enumerabilità

Gli elementi di un WeakMap non possono essere iterati o enumerati. Questo significa che non esistono metodi come forEach, keys, values, o entries per WeakMap.

3. Solo Chiavi Oggetto

A differenza dei normali Map, dove le chiavi possono essere di qualsiasi tipo, in un WeakMap solo gli oggetti possono essere utilizzati come chiavi.

Applicazioni Comuni dei WeakMap

1. Memorizzazione di Dati Privati

I WeakMap sono utili per memorizzare dati privati per oggetti, garantendo che i dati associati vengano rimossi dalla memoria quando l’oggetto non è più necessario.

Esempio

let datiPrivati = new WeakMap();

class Persona {
  constructor(nome) {
    this.nome = nome;
    datiPrivati.set(this, { età: 30 });
  }

  getEtà() {
    return datiPrivati.get(this).età;
  }
}

let mario = new Persona("Mario");
console.log(mario.getEtà()); // Output: 30

2. Gestione di Eventi e Listener

Puoi usare un WeakMap per memorizzare dati relativi agli eventi e ai listener, assicurandoti che i dati vengano rimossi quando gli oggetti a cui sono associati non sono più referenziati.

Esempio

let listenerDati = new WeakMap();

function registraListener(elemento, listener) {
  listenerDati.set(elemento, listener);
  elemento.addEventListener("click", listener);
}

function rimuoviListener(elemento) {
  let listener = listenerDati.get(elemento);
  if (listener) {
    elemento.removeEventListener("click", listener);
    listenerDati.delete(elemento);
  }
}

Best Practices per l’Uso dei WeakMap

  • Utilizza WeakMap per Associazioni Temporanee: Usa WeakMap quando vuoi associare dati a un oggetto solo finché l’oggetto esiste. Questo è particolarmente utile per le cache temporanee e i dati associati dinamicamente.
  • Non Usare WeakMap per Dati Importanti: Poiché i dati in un WeakMap possono essere rimossi automaticamente dal garbage collector, non utilizzare WeakMap per memorizzare dati critici che devono persistere.
  • Non Dipendere dall’Enumerabilità: Poiché non puoi iterare su un WeakMap, non fare affidamento su di esso per gestire collezioni di dati che richiedono enumerazione.

Conclusione

I WeakMap in JavaScript offrono una soluzione potente per gestire associazioni deboli tra oggetti e dati, garantendo al contempo un’efficiente gestione della memoria. Comprendere come e quando utilizzare i WeakMap può migliorare la performance e l’affidabilità delle tue applicazioni, specialmente in scenari complessi come la gestione di cache temporanee e la memorizzazione di dati privati. Sfruttando le caratteristiche uniche dei WeakMap, puoi assicurarti che i tuoi oggetti e i loro dati associati siano gestiti in modo ottimale dal motore JavaScript.