Het Map-object in JavaScript: methodes, iteratie en WeakMap

Het Map-object in JavaScript: methodes, iteratie en WeakMap

Map is een constructor die je in een aantal gevallen een eenvoudigere en efficiëntere manier geeft om data te structureren en te benaderen. 

Dit is in 3 punten wat een Map-object concreet doet:

  • Een Map bevat sleutel-waardeparen waarbij de sleutels van elk datatype mogen zijn.

  • Een Map onthoudt de oorspronkelijke volgorde waarin de sleutels zijn toegevoegd.

  • Een Map heeft een eigenschap die zijn omvang bevat.

Handige methodes van het JavaScript Map-object

  • clear() – verwijdert alle elementen uit het map-object.
  •  delete(key) – verwijdert het element dat bij de sleutel hoort. De methode geeft true terug als het element in het Map-object zat, en anders false.
  •  entries() – geeft een nieuw Iterator-object terug met per element van het map-object een array [key, value]. De volgorde van de entries in het Map-object is de volgorde van invoegen.
  •  forEach(callback[, thisArg]) – roept een callback aan voor elk sleutel-waardepaar van de Map, in volgorde van invoegen. De optionele parameter thisArg bepaalt de waarde van this in elke callback.
  •  get(key) – geeft de waarde terug die bij de sleutel hoort. Bestaat de sleutel niet, dan is het resultaat undefined.
  •  has(key) – geeft true terug als er een waarde bij de sleutel bestaat, en anders false.
  •  keys() –  geeft een nieuwe Iterator terug met de sleutels van de elementen, in volgorde van invoegen.
  •  set(key, value) – zet de waarde van de sleutel in het map-object. De methode geeft het map-object zelf terug, zodat je haar aan andere methodes kunt vastknopen.
  •  values() geeft een nieuw iterator-object terug met de waarde van elk element, in volgorde van invoegen.

Praktijkvoorbeelden met het JavaScript Map-object

Een nieuw Map-object aanmaken

Stel dat je een lijst met gebruikersobjecten hebt, zoals deze:

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

En stel dat je daar een Map-object van gebruikers en rollen bij nodig hebt. Dan gebruik je deze code:

javascript
let userRoles = new Map();

userRoles is een instantie van Map en het type ervan is een object, zoals het volgende voorbeeld laat zien:

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

Elementen aan een Map toevoegen

Om een gebruiker een rol te geven, gebruik je de methode set():

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

De methode set() koppelt de gebruiker kevin aan de rol admin. Omdat set() chainable is, scheelt dat je wat typewerk, zoals in dit voorbeeld:

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

Een Map-object initialiseren met een iterable

Zoals eerder gezegd kun je een iterable object aan de constructor Map() meegeven:

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

Een element ophalen via zijn sleutel

Wil je de rol van Kévin zien, dan gebruik je de methode get():

javascript
userRoles.get(kevin); // admin

Geef je een sleutel mee die niet bestaat, dan geeft de methode get() undefined terug.

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

Controleren of een element bestaat, op sleutel

Om te controleren of een sleutel in ons Map-object voorkomt, gebruik je de methode has().

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

Het aantal elementen in ons Map-object opvragen

De eigenschap size geeft het aantal entries in het Map-object terug.

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

Over de ‘sleutels’ van je Map-object itereren

Om de sleutels van een Map-object te krijgen, gebruik je de methode keys(). Die keys() geeft een nieuw iterator-object terug met de sleutels van de elementen van het object.

Het volgende voorbeeld toont de naam van elke gebruiker in de 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);
}

Uitvoer:

javascript
Kévin Feige
Pierre Rocher
Jean Moulin

Over de waarden van je Map-object itereren

Op dezelfde manier gebruik je de methode values() om een iterator-object te krijgen met de waarden van alle elementen van je Map-object:

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

Uitvoer:

javascript
admin
éditeur
abonné

Over de entries van je Map-object itereren

Daarnaast geeft de methode entries() een iterator-object terug met per element van het Map-object een array [key,value]:

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

Om de lus natuurlijker te laten lezen, kun je destructuring gebruiken:

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

Naast de lus for…of kun je de methode forEach() van het map-object gebruiken:

De sleutels of de waarden van een Map naar een array omzetten

Soms werk je liever met een array dan met een iterable object, en daarvoor gebruik je de spread-operator.

Het volgende voorbeeld zet de sleutels van alle elementen om naar een array met sleutels:

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

Uitvoer:

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

En dit voorbeeld zet de waarden van de elementen om naar een array:

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

Uitvoer:

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

Een element op sleutel verwijderen

Om een entry uit je Map-object te verwijderen, gebruik je de methode delete().

javascript
userRoles.delete(pierre);

Alle elementen uit een Map-object verwijderen

Om alle entries uit het Map-object te verwijderen, gebruik je de methode clear():

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

WeakMap

Een WeakMap lijkt op een Map, met dit verschil dat de sleutels van een WeakMap objecten moeten zijn. Zodra een referentie naar een sleutel (een object) buiten scope raakt, wordt de bijbehorende waarde automatisch uit het geheugen vrijgegeven.

Een WeakMap heeft maar een deel van de methodes van een Map-object:

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

Dit zijn de belangrijkste verschillen tussen een Map en een WeakMap:

  • Over de elementen van een WeakMap kun je niet itereren.
  • Je kunt niet alle elementen in één keer wissen.
  • De omvang van een WeakMap kun je niet opvragen.

In deze tutorial heb je geleerd hoe je met het JavaScript-object Map werkt en met de methodes waarmee je de entries ervan makkelijk bewerkt.

JavaScript

Damien Flandrin Webdeveloper sinds 2010, maker van Gekkode en Email Impact. Elk artikel wordt vóór publicatie getest op een echt project. Contact
Nieuwsbrief

Nieuwe tests, tutorials en projecten, per e-mail.

Reproduceerbare tests, geversioneerde code, gedateerde resultaten. Nooit spam.