`Map` Object
This article explains the Map object.
We will explain step by step, from basic operations to practical examples that are useful in real-world scenarios.
YouTube Video
Map Object
Map is a collection that stores key-value pairs. It is similar to an object, but differs in that any type, such as objects, functions, or primitives, can be used as keys, and the insertion order is preserved.
Basics of Map
First, let's look at how to create a Map and perform basic operations.
The following code is a minimal example that creates an empty map, adds keys, and retrieves values.
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 this code, you can add elements with
set, retrieve values withget, and check the number of elements withsize. Mapmaintains insertion order, making it suitable for order-dependent processing.
Behavior of set, get, has, and delete
Here are examples of typical read, write, existence check, and delete operations.
With the following code, you can check the return values and effects of each method.
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 }
getreturnsundefinedif the key does not exist.haschecks for the existence of a key, anddeleteremoves a key.- Also, since
setreturns the map itself, method chaining is possible.
Any type can be used as a key (using objects as keys)
One of the main advantages of Map is that you can use objects directly as keys.
The following example shows how to associate values in a Map using objects as keys.
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'
- When using objects as keys, it is important that they are the same reference. Even if their contents are the same, objects with different references are treated as different and are not the same key.
Iteration (looping)
Map preserves insertion order, so iteration is often used.
Below, we show how to use for...of, forEach, and the keys(), values(), and entries() methods.
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()returns an array of[key, value]pairs, which can be turned into an array using the spread syntax. Note that the callback forforEachreceives arguments in the ordervalue, key.
Converting Between Map and Object
You can convert an existing object to a Map, or convert a Map to a plain object or 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]]
- Using
Object.entriesandObject.fromEntriesmakes conversion easy. However, since object keys are limited to strings or symbols, non-string keys are lost when converting back to an object.
Practical Pattern: Frequency Counting (Count Map)
When counting the frequency of elements in an array, using a Map makes the process simpler.
The following code is an example of using a map to count the frequencies of strings in an array and sort them.
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]]
- Using a
Mapallows for easy existence checks and updates. This can be done with objects as well, butMapcan be more intuitive when working with arbitrary keys.
Notes on Map and JSON.stringify (Serialization)
JSON.stringify cannot serialize a Map directly. If you need to save a Map, you must convert it first.
The following example shows how to convert a Map to an array before turning it into JSON, and how to restore it.
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 that need to be saved or transmitted should be converted to arrays before serialization. When restoring, use
JSON.parseto convert into an array, then turn it back into a Map.
Introduction to WeakMap and How to Use It
WeakMap differs in that its keys are weakly referenced (subject to garbage collection).
It is useful for holding cache or metadata with objects as keys, automatically releasing them when the key object is collected.
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
WeakMapcannot be enumerated or have its size checked, but is useful for preventing memory leaks.
Summary
Map is a convenient collection that, unlike objects, allows any type as key and preserves insertion order. By understanding everything from basic operations to advanced usage, you can manage data more flexibly and intuitively. By using Object and Map appropriately according to the use case, you can greatly improve code clarity and readability.
You can follow along with the above article using Visual Studio Code on our YouTube channel. Please also check out the YouTube channel.