Scoprire le Potenzialità di WeakMap in JavaScript

 


In JavaScript, spesso lavoriamo con strutture dati come Map o Set per associare chiavi a valori o memorizzare collezioni di elementi. Tuttavia, quando si ha la necessità di associare dati a oggetti senza influenzare il ciclo di vita di quegli oggetti, WeakMap diventa uno strumento potente e insostituibile.

🔗 Ti piace Techelopment? Dai un'occhiata al sito per tutti i dettagli!

✅ Cos’è un WeakMap?

Un WeakMap è una collezione di coppie chiave/valore in cui:

  • Le chiavi devono essere oggetti (non primitive).
  • I riferimenti alle chiavi sono deboli, ovvero non impediscono il garbage collection.
  • Non è iterabile: non possiamo usare for...of, .keys() o .entries() per esplorarne i contenuti.

Queste caratteristiche rendono WeakMap particolarmente utile in scenari dove si vuole collegare dati a oggetti in modo non intrusivo e senza rischio di memory leak.


🔍 Perché usare WeakMap?

  • Gestione della memoria: Le chiavi deboli permettono la rimozione automatica degli oggetti non più usati.
  • Integrazione trasparente: Permette di associare dati ad oggetti senza modificarli.
  • Sicurezza e incapsulamento: Le chiavi non sono accessibili dall’esterno; nessuno può enumerarle.

📊 WeakMap vs Map: Confronto Diretto

Caratteristica Map WeakMap
Chiavi Oggetti, primitive Solo oggetti
Garbage collection Chiavi mantenute in memoria Chiavi debolmente referenziate
Iterabilità Sì, con .keys(), .forEach(), ecc. No
Visibilità Accessibile con .size, .entries() Inaccessibile
Utilizzo tipico Collezioni generiche Dati privati, cache temporanee

📌 Punti chiave

  • Map trattiene le chiavi in memoria, quindi può causare memory leak se non gestita bene.

  • WeakMap non trattiene le chiavi, quindi è ideale per memorizzare dati associati ad oggetti in modo temporaneo o privato.

  • Questo comportamento è cruciale per:

    • cache automatiche

    • gestione di risorse dinamiche (es. DOM)

    • dati privati di oggetti che possono essere distrutti in modo naturale


Per comprendere meglio gli impatti su Garbage collector, vediamo nel dettaglio un esempio concreto.

🧹 Esempio concreto: WeakMap e Garbage Collection

🎯 Obiettivo

Associare dati temporanei a elementi DOM senza causare memory leak.

const elementData = new WeakMap();

function attachMetadata(element) {
  const data = {
    clickedAt: Date.now(),
    temporarySetting: Math.random()
  };
  elementData.set(element, data);
}

function handleClick(event) {
  const element = event.target;
  attachMetadata(element);
  console.log('Metadata stored:', elementData.get(element));
}

let button = document.createElement('button');
button.textContent = 'Click me';
document.body.appendChild(button);

button.addEventListener('click', handleClick);

setTimeout(() => {
  document.body.removeChild(button);
  button = null; // Remove last reference

  // Now both the DOM element and its metadata can be garbage collected
}, 5000);

Con una Map, l’elemento e i dati associati sarebbero rimasti in memoria.
Con WeakMap, appena l’elemento non ha più riferimenti attivi, tutto viene pulito automaticamente dal garbage collector.


🛑 Limitazioni di WeakMap

❌ 1. Non è iterabile: non puoi accedere a tutte le chiavi o valori

const wm = new WeakMap();
const obj = {};
wm.set(obj, 'data');

for (const [key, value] of wm) {
  console.log(key, value); // ❌ TypeError: wm is not iterable
}

❌ 2. Le chiavi devono essere oggetti: non puoi usare stringhe, numeri, ecc.

const wm = new WeakMap();
wm.set('user', 'data'); // ❌ TypeError: Invalid value used as weak map key

❌ 3. Nessuna proprietà .size

const wm = new WeakMap();
const a = {}, b = {};
wm.set(a, 1);
wm.set(b, 2);

console.log(wm.size); // ❌ undefined

❌ 4. Nessuna visibilità sul contenuto

const wm = new WeakMap();
const obj = {};
wm.set(obj, 'secret');

console.log(wm.has(obj));       // ✔️ true
console.log([...wm.keys()]);    // ❌ TypeError: wm.keys is not a function

🧪 Esempi pratici di utilizzo di una WeakMap 

📌 1. Associare metadati a oggetti

In questo esempio, i metadati non sono direttamente collegati all’oggetto user, ma vengono memorizzati in una struttura separata e invisibile al di fuori delle funzioni definite.
const metaData = new WeakMap();

function setMetadata(obj, data) {
  metaData.set(obj, data);
}

function getMetadata(obj) {
  return metaData.get(obj);
}

const user = { name: 'Alice' };

setMetadata(user, { role: 'admin' });

console.log(getMetadata(user)); // { role: 'admin' }

📌 2. Proprietà private in una classe

Qui WeakMap viene utilizzato per tenere i dati count fuori dalla portata diretta del codice utente, emulando la visibilità privata.
const privateProps = new WeakMap();

class Counter {
  constructor() {
    privateProps.set(this, { count: 0 });
  }

  increment() {
    const data = privateProps.get(this);
    data.count++;
  }

  getCount() {
    return privateProps.get(this).count;
  }
}

const counter = new Counter();
counter.increment();
counter.increment();

console.log(counter.getCount()); // 2
console.log(counter.count);      // undefined

📌 3. Cache automatica per funzioni

Con WeakMap, la cache associata a data verrà rimosso automaticamente quando data non sarà più utilizzato, evitando accumuli di memoria non voluti.
const cache = new WeakMap();

function process(obj) {
  if (cache.has(obj)) {
    return cache.get(obj);
  }

  const result = computeHeavyTask(obj);
  cache.set(obj, result);
  return result;
}

function computeHeavyTask(obj) {
  return obj.value * 1000;
}

const data = { value: 5 };

console.log(process(data)); // 5000
console.log(process(data)); // 5000, cached


🎯 Conclusione

WeakMap è un potente strumento per:

  • Associare dati privati a oggetti senza modificarli
  • Gestire cache in modo automatico e sicuro
  • Prevenire memory leak in scenari dinamici (DOM, componenti)

Non sostituisce Map, ma si rivela essenziale in contesti dove la gestione della memoria e la privacy dei dati sono fondamentali.



Follow me #techelopment

Official site: www.techelopment.it
facebook: Techelopment
instagram: @techelopment
X: techelopment
Bluesky: @techelopment
telegram: @techelopment_channel
whatsapp: Techelopment
youtube: @techelopment