`Oggetto Map`

Questo articolo spiega l'oggetto Map.

Spiegheremo passo dopo passo, dalle operazioni di base agli esempi pratici utili in scenari reali.

YouTube Video

Oggetto Map

Map è una collezione che memorizza coppie chiave-valore. È simile a un oggetto, ma si differenzia per il fatto che qualsiasi tipo, come oggetti, funzioni o primitivi, può essere utilizzato come chiave e l’ordine di inserimento viene mantenuto.

Nozioni di base su Map

Per prima cosa, vediamo come creare una Map ed eseguire operazioni di base.

Il seguente codice è un esempio minimo che crea una mappa vuota, aggiunge delle chiavi e recupera i valori.

1// Create an empty Map and add key-value pairs
2const m = new Map();
3m.set('a', 1);
4m.set('b', 2);
5
6console.log(m.get('a')); // 1
7console.log(m.size);     // 2
  • In questo codice, puoi aggiungere elementi con set, recuperare valori con get e verificare il numero di elementi con size.
  • Map mantiene l'ordine di inserimento, rendendola adatta per elaborazioni dipendenti dall'ordine.

Comportamento di set, get, has e delete

Ecco esempi di operazioni tipiche di lettura, scrittura, controllo dell'esistenza ed eliminazione.

Con il codice seguente, puoi verificare i valori restituiti e gli effetti di ciascun metodo.

 1// Demonstrate set, get, has, and delete
 2const m2 = new Map();
 3m2.set('x', 10);
 4console.log(m2.has('x'));  // true
 5console.log(m2.get('y'));  // undefined
 6
 7m2.delete('x');
 8console.log(m2.has('x'));  // false
 9
10// set returns the map itself, allowing method chaining
11m2.set('a', 1).set('b', 2);
12console.log(m2);  // Map { 'a' => 1, 'b' => 2 }
  • get restituisce undefined se la chiave non esiste. has verifica l'esistenza di una chiave e delete rimuove una chiave.
  • Inoltre, poiché set restituisce la mappa stessa, è possibile concatenare i metodi.

Qualsiasi tipo può essere utilizzato come chiave (utilizzando oggetti come chiavi)

Uno dei principali vantaggi di Map è che si possono usare oggetti direttamente come chiavi.

Il seguente esempio mostra come associare valori in una Map usando oggetti come chiavi.

 1// Use objects as keys in a Map
 2const keyObj = { id: 1 };
 3const keyFunc = () => {};
 4const objMap = new Map();
 5
 6// Another object with the same content but a different reference
 7const anotherKeyObj = { id: 1 };
 8
 9objMap.set(keyObj, 'objectValue');
10objMap.set(keyFunc, 'functionValue');
11objMap.set(anotherKeyObj, 'anotherValue');
12
13console.log(objMap.get(keyObj));         // 'objectValue'
14console.log(objMap.get(keyFunc));        // 'functionValue'
15console.log(objMap.get(anotherKeyObj));  // 'anotherValue'
  • Quando si usano oggetti come chiavi, è importante che abbiano il medesimo riferimento. Anche se il loro contenuto è identico, oggetti con riferimenti diversi sono considerati diversi e non corrispondono alla stessa chiave.

Iterazione (ciclo)

Map preserva l'ordine di inserimento, quindi l'iterazione viene spesso utilizzata.

Di seguito, mostriamo come utilizzare for...of, forEach e i metodi keys(), values() ed entries().

 1// Iterating a Map with for...of and forEach
 2const iterMap = new Map([['a', 1], ['b', 2], ['c', 3]]);
 3
 4// for...of over entries (default)
 5for (const [key, value] of iterMap) {
 6  console.log(key, value);
 7}
 8
 9// forEach callback
10iterMap.forEach((value, key) => {
11  console.log(key, value);
12});
13
14// keys() and values()
15console.log([...iterMap.keys()]);   // ['a','b','c']
16console.log([...iterMap.values()]); // [1,2,3]
  • entries() restituisce un array di coppie [chiave, valore], che può essere trasformato in un array utilizzando la sintassi spread. Nota che la callback di forEach riceve gli argomenti nell'ordine valore, chiave.

Conversione tra Map e Object

Puoi convertire un oggetto esistente in una Map o convertire una Map in un oggetto semplice o in un array.

 1// Convert between Map and Object / Array
 2const obj = { a: 1, b: 2 };
 3const mapFromObj = new Map(Object.entries(obj)); // Object -> Map
 4console.log(mapFromObj.get('a')); // 1
 5
 6const objFromMap = Object.fromEntries(mapFromObj); // Map -> Object
 7console.log(objFromMap); // { a: 1, b: 2 }
 8
 9const arrayFromMap = [...mapFromObj]; // Map -> Array of [key, value]
10console.log(arrayFromMap); // [['a',1], ['b',2]]
  • Utilizzando Object.entries e Object.fromEntries, la conversione è semplice. Tuttavia, poiché le chiavi negli oggetti sono limitate a stringhe o simboli, le chiavi non-stringa vengono perse quando si riconverte in un oggetto.

Schema pratico: conteggio delle frequenze (Count Map)

Quando si deve contare la frequenza degli elementi in un array, usare una Map rende il processo più semplice.

Il codice seguente è un esempio di utilizzo di una map per contare la frequenza delle stringhe in un array e ordinarle.

1// Count frequencies with Map
2const arr = ['apple','banana','apple','orange','banana','apple'];
3const freq = new Map();
4
5for (const item of arr) {
6  freq.set(item, (freq.get(item) || 0) + 1);
7}
8
9console.log([...freq.entries()]); // [['apple',3], ['banana',2], ['orange',1]]
  • Utilizzare una Map consente controlli e aggiornamenti di esistenza facilitati. Questo può essere fatto anche con gli oggetti, ma Map può essere più intuitivo quando si lavora con chiavi arbitrarie.

Note su Map e JSON.stringify (Serializzazione)

JSON.stringify non può serializzare direttamente una Map. Se hai bisogno di salvare una Map, devi prima convertirla.

Il seguente esempio mostra come convertire una Map in un array prima di trasformarla in JSON, e come ripristinarla.

1// Serialize and deserialize a Map
2const m3 = new Map([['x', 1], ['y', 2]]);
3const json = JSON.stringify([...m3]); // convert to array first
4console.log(json); // '[["x",1],["y",2]]'
5
6const restored = new Map(JSON.parse(json));
7console.log(restored.get('x')); // 1
  • Le Map che devono essere salvate o trasmesse dovrebbero essere convertite in array prima della serializzazione. Durante il ripristino, usa JSON.parse per convertirlo in un array, e poi riportalo a Map.

Introduzione a WeakMap e come utilizzarla

WeakMap si differenzia perché le sue chiavi sono debolmente referenziate (soggette a garbage collection).

È utile per mantenere cache o metadati con oggetti come chiavi, rilasciandoli automaticamente quando l'oggetto chiave viene raccolto.

1// WeakMap for metadata tied to object lifecycle
2const wm = new WeakMap();
3let obj = {};
4wm.set(obj, { meta: 'info' });
5console.log(wm.get(obj)); // { meta: 'info' }
6
7obj = null; // now the object can be GC'd and its entry removed from WeakMap
  • WeakMap non può essere enumerata né la sua dimensione può essere controllata, ma è utile per prevenire perdite di memoria.

Riepilogo

Map è una collezione comoda che, a differenza degli oggetti, consente di usare qualsiasi tipo come chiave e preserva l'ordine di inserimento. Comprendendo tutto, dalle operazioni di base all’uso avanzato, puoi gestire i dati in modo più flessibile e intuitivo. Utilizzando Object e Map in modo appropriato in base al caso d'uso, puoi migliorare notevolmente chiarezza e leggibilità del codice.

Puoi seguire l'articolo sopra utilizzando Visual Studio Code sul nostro canale YouTube. Controlla anche il nostro canale YouTube.

YouTube Video