Het `Map`-object
Dit artikel legt het Map-object uit.
We leggen stap voor stap uit, van basisbewerkingen tot praktische voorbeelden die nuttig zijn in echte situaties.
YouTube Video
Het Map-object
Map is een collectie die sleutel-waardeparen opslaat. Het lijkt op een object, maar verschilt doordat elk type, zoals objecten, functies of primitieve waarden, als sleutel kan worden gebruikt en de invoegvolgorde behouden blijft.
Basisprincipes van Map
Laten we eerst kijken hoe je een Map aanmaakt en basisbewerkingen uitvoert.
De volgende code is een minimaal voorbeeld dat een lege map aanmaakt, sleutels toevoegt en waarden ophaalt.
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 deze code kun je elementen toevoegen met
set, waarden ophalen metgeten het aantal elementen controleren metsize. Mapbehoudt de invoegvolgorde, wat het geschikt maakt voor volgordeafhankelijke verwerking.
Gedrag van set, get, has en delete
Hier zijn voorbeelden van typische lees-, schrijf-, bestaanscontrole- en verwijderbewerkingen.
Met de onderstaande code kun je de retourwaarden en effecten van elke methode controleren.
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 }
getretourneertundefinedals de sleutel niet bestaat.hascontroleert of een sleutel bestaat, endeleteverwijdert een sleutel.- Aangezien
setde map zelf retourneert, is method chaining mogelijk.
Elk type kan als sleutel worden gebruikt (objecten als sleutels gebruiken)
Een van de grootste voordelen van Map is dat je objecten direct als sleutel kunt gebruiken.
Het volgende voorbeeld laat zien hoe je waarden in een Map koppelt met objecten als sleutels.
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'
- Als je objecten als sleutel gebruikt, is het belangrijk dat ze dezelfde referentie zijn. Zelfs als hun inhoud hetzelfde is, worden objecten met verschillende referenties als verschillend beschouwd en zijn het niet dezelfde sleutel.
Iteratie (lussen)
Map behoudt de invoegvolgorde, dus iteratie wordt vaak gebruikt.
Hieronder laten we zien hoe je for...of, forEach en de methoden keys(), values() en entries() gebruikt.
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()retourneert een array van[key, value]paren, die met de spread-syntax in een gewone array kunnen worden omgezet. Let op dat de callback vanforEachargumenten ontvangt in de volgordevalue, key.
Conversie tussen Map en Object
Je kunt een bestaand object omzetten naar een Map, of een Map omzetten naar een gewoon object of een 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]]
- Het gebruik van
Object.entriesenObject.fromEntriesmaakt conversie eenvoudig. Aangezien object-sleutels beperkt zijn tot strings of symbolen, gaan niet-string-sleutels verloren bij het terugconverseren naar een object.
Praktisch patroon: Frequentietelling (tellingen met Map)
Bij het tellen van de frequentie van elementen in een array maakt het gebruik van een Map het proces eenvoudiger.
De onderstaande code is een voorbeeld waarin een map wordt gebruikt om de frequenties van strings in een array te tellen en te sorteren.
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]]
- Met een
Mapkun je eenvoudig controleren of iets bestaat en bijwerken. Dit kan ook met objecten gedaan worden, maarMapis vaak intuïtiever wanneer je met willekeurige sleutels werkt.
Opmerkingen over Map en JSON.stringify (serialisatie)
JSON.stringify kan een Map niet direct serialiseren. Als je een Map wilt opslaan, moet je deze eerst omzetten.
Het volgende voorbeeld laat zien hoe je een Map omzet naar een array voordat je het naar JSON converteert, en hoe je het weer herstelt.
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
- Maps die opgeslagen of verzonden moeten worden, moeten eerst worden omgezet naar arrays voordat ze geserialiseerd worden. Gebruik bij het herstellen
JSON.parseom het naar een array om te zetten, en zet het dan weer om in een Map.
Introductie tot WeakMap en hoe het te gebruiken
WeakMap verschilt doordat de sleutels zwak worden gerefereerd (onderhevig aan garbage collection).
Het is handig voor het bijhouden van cache of metadata met objecten als sleutels, die automatisch vrijkomen wanneer het sleutelobject wordt opgeruimd.
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
WeakMapkan niet worden doorlopen of de grootte kan niet worden gecontroleerd, maar is handig om geheugengebrek te voorkomen.
Samenvatting
Map is een handige collectie die, anders dan objecten, elk type als sleutel toestaat en de invoegvolgorde behoudt. Door alles van de basisbewerkingen tot het geavanceerd gebruik te begrijpen, kun je data flexibeler en intuïtiever beheren. Door Object en Map op de juiste manier te gebruiken, afhankelijk van de situatie, kun je de duidelijkheid en leesbaarheid van je code sterk verbeteren.
Je kunt het bovenstaande artikel volgen met Visual Studio Code op ons YouTube-kanaal. Bekijk ook het YouTube-kanaal.