Oggetto Map in JavaScript: metodi, iterazione e WeakMap

Oggetto Map in JavaScript: metodi, iterazione e WeakMap

Map è un costruttore che offre un modo più semplice ed efficiente di strutturare i dati e di accedervi in alcuni casi d’uso.

In tre punti, ecco che cosa fa concretamente un oggetto Map:

  • Map contiene coppie chiave-valore, dove le chiavi possono essere di qualsiasi tipo di dato.

  • Map ricorda l’ordine di inserimento originale delle chiavi.

  • Map espone una proprietà che ne indica la dimensione.

Metodi utili dell’oggetto Map in JavaScript

  • clear() – rimuove tutti gli elementi dalla map.
  • delete(key) – rimuove l’elemento indicato dalla chiave. Restituisce true se l’elemento era presente nella Map, false altrimenti.
  • entries() – restituisce un nuovo Iterator che contiene un array [key, value] per ogni elemento della map. L’ordine è quello di inserimento.
  • forEach(callback[, thisArg]) – richiama una callback per ogni coppia chiave-valore della Map, nell’ordine di inserimento. Il parametro opzionale thisArg definisce il valore di this per ogni callback.
  • get(key) – restituisce il valore associato alla chiave. Se la chiave non esiste, restituisce undefined.
  • has(key) – restituisce true se esiste un valore associato alla chiave, altrimenti false.
  • keys() – restituisce un nuovo Iterator che contiene le chiavi degli elementi nell’ordine di inserimento.
  • set(key, value) – imposta il valore della chiave nella map. Restituisce la map stessa, quindi puoi concatenare il metodo con altri.
  • values() restituisce un nuovo oggetto iteratore che contiene i valori di ogni elemento nell’ordine di inserimento.

Esempi d’uso dell’oggetto Map di JavaScript

Creare un nuovo oggetto Map

Supponiamo che tu abbia un elenco di oggetti utente come questo:

javascript
let pierre = {name: 'Pierre Lepez'},
    jean = {name: 'Jean Doe'},
    kevin = {name: 'Kévin Gomez'};

Immagina ora di dover creare una Map di utenti e ruoli. In questo caso usi il codice seguente:

javascript
let userRoles = new Map();

userRoles è un’istanza dell’oggetto Map e il suo tipo è object, come mostra l’esempio seguente:

javascript
console.log(typeof(userRoles)); // object
console.log(userRoles instanceof Map); // true

Aggiungere elementi a una Map

Per assegnare un ruolo a un utente usi il metodo set():

javascript
userRoles.set(kevin, 'admin');

Il metodo set() associa l’utente kevin al ruolo di amministratore. Dato che set() è concatenabile, puoi risparmiare qualche battuta come in questo esempio:

javascript
userRoles.set(pierre, 'éditeur')
          .set(jean, 'abonné');

Inizializzare una Map con un oggetto iterabile

Come detto poco fa, puoi passare un oggetto iterabile al costruttore Map():

javascript
let userRoles = new Map([
    [kevin, 'admin'],
    [pierre, 'éditeur'],
    [jean, 'abonné']
]);

Ottenere un elemento tramite la chiave

Se vuoi vedere i ruoli di Kévin, usi il metodo get():

javascript
userRoles.get(kevin); // admin

Se passi una chiave che non esiste, il metodo get() restituisce undefined.

javascript
let foo = {name: 'Foo'};
userRoles.get(foo); //undefined

Verificare l’esistenza di un elemento dalla chiave

Per controllare se una chiave esiste nella nostra Map usi il metodo has().

javascript
userRoles.has(foo); // false
userRoles.has(pierre); // true

Contare gli elementi della Map

La proprietà size restituisce il numero di voci dell’oggetto Map.

javascript
console.log(userRoles.size); // 3

Iterare sulle chiavi della Map

Per ottenere le chiavi di una Map usi il metodo keys(). Il metodo keys() restituisce un nuovo oggetto iteratore che contiene le chiavi degli elementi.

L’esempio seguente stampa il nome degli utenti presenti nella map userRoles.

javascript
let kevin = { name: 'Kévin Feige' },
  pierre = { name: 'Pierre Rocher' },
  jean = { name: 'Jean Moulin' };

let userRoles = new Map([
    [kevin, 'admin'],
    [pierre, 'éditeur'],
    [jean, 'abonné']
]);

for (const user of userRoles.keys()) {
  console.log(user.name);
}

Output:

javascript
Kévin Feige
Pierre Rocher
Jean Moulin

Iterare sui valori della Map

Allo stesso modo puoi usare il metodo values() per ottenere un oggetto iteratore con i valori di tutti gli elementi della Map:

javascript
let kevin = { name: 'Kévin Feige' },
  pierre = { name: 'Pierre Rocher' },
  jean = { name: 'Jean Moulin' };

let userRoles = new Map([
    [kevin, 'admin'],
    [pierre, 'éditeur'],
    [jean, 'abonné']
]);

for (const role of userRoles.values()) {
  console.log(role);
}

Output:

javascript
admin
éditeur
abonné

Iterare sugli elementi della Map

Il metodo entries() restituisce invece un oggetto iteratore che contiene un array [key,value] per ogni elemento della Map:

javascript
let kevin = { name: 'Kévin Feige' },
  pierre = { name: 'Pierre Rocher' },
  jean = { name: 'Jean Moulin' };

let userRoles = new Map([
    [kevin, 'admin'],
    [pierre, 'éditeur'],
    [jean, 'abonné']
]);

for (const role of userRoles.entries()) {
  console.log(`${role[0].name}: ${role[1]}`);
}

Per rendere l’iterazione più naturale puoi ricorrere alla destrutturazione:

javascript
let kevin = { name: 'Kévin Feige' },
  pierre = { name: 'Pierre Rocher' },
  jean = { name: 'Jean Moulin' };

let userRoles = new Map([
    [kevin, 'admin'],
    [pierre, 'éditeur'],
    [jean, 'abonné']
]);

userRoles.forEach((role, user) => console.log(`${user.name}: ${role}`));

Oltre al ciclo for…of, puoi usare il metodo forEach() della map:

Convertire chiavi o valori della Map in un array

A volte preferisci lavorare con un array invece che con un oggetto iterabile: in quel caso usi l’operatore di spread (spread operator).

L’esempio seguente converte le chiavi di ogni elemento in un array di chiavi:

javascript
var keys = [...userRoles.keys()];
console.log(keys);

Output:

javascript
[ { name: 'Kévin Feige' },
  { name: 'Pierre Rocher' },
  { name: 'Jean Moulin' } ]

E quest’altro converte i valori degli elementi in un array:

javascript
let roles = [...userRoles.values()];
console.log(roles);

Output:

javascript
[ 'admin', 'éditeur', 'abonné' ]

Rimuovere un elemento dalla sua chiave

Per eliminare una voce dalla tua Map usi il metodo delete().

javascript
userRoles.delete(pierre);

Rimuovere tutti gli elementi di una Map

Per eliminare tutte le voci dell’oggetto Map usi il metodo clear():

javascript
userRoles.clear();
console.log(userRoles.size); // 0

WeakMap

Una WeakMap è simile a una Map, con la differenza che le chiavi di una WeakMap devono essere oggetti. Significa che, quando il riferimento a una chiave (un oggetto) esce dallo scope, il valore corrispondente viene liberato automaticamente dalla memoria.

Una WeakMap espone soltanto un sottoinsieme dei metodi di una Map:

  • get(key)
  • set(key, value)
  • has(key)
  • delete(key)

Ecco le differenze principali tra una Map e una WeakMap:

  • Gli elementi di una WeakMap non si possono iterare.
  • Non si possono cancellare tutti gli elementi in una volta sola.
  • Non si può conoscere la dimensione di una WeakMap.

In questo tutorial hai imparato a lavorare con l’oggetto JavaScript Map e con i suoi metodi utili per manipolarne le voci.

JavaScript

Damien Flandrin Sviluppatore web dal 2010, creatore di Gekkode e di Email Impact. Ogni articolo è testato su un progetto reale prima della pubblicazione. Contatti
Newsletter

I nuovi test, tutorial e progetti, via e-mail.

Test riproducibili, codice versionato, risultati datati. Mai spam.