Maps in JavaScript
A JavaScript Map is an object that stores key/value pairs. You can get()
or set()
the value associated with a key, or use has()
to check whether the map has a given key.
const map = new Map();
map.get('answer'); // undefined
map.has('answer'); // false
map.set('answer', 42);
map.get('answer'); // 42
map.has('answer'); // true
Before ES6, JavaScript objects were often used as maps. Maps have several advantages over objects for storing user data. First, objects have special properties that may collide with key names. If you're not careful, you can end up with a prototype poisoning security vulnerability. That's why you need to be careful whether you use in
or hasOwnProperty()
if you're using objects as maps.
const obj = {};
const map = new Map();
obj.answer = 42;
map.set('answer', 42);
'answer' in obj; // true
map.has('answer'); // true
'prototype' in obj; // true
map.has('prototype'); // false
'__proto__' in obj; // true
map.has('constructor'); // false
Maps can also store arbitrary keys, whereas objects can only store strings as keys. For example, you can store a JavaScript date key in a map. If you try to store a date as a key in an object, JavaScript will convert the key to a string first.
const map = new Map();
const date = new Date('2019-06-01');
map.set(date, 'test1');
map.set(date.toString(), 'test2');
map.get(date); // 'test1'
map.get(date.toString()); // 'test2'
const obj = {};
obj[date] = 'test1';
obj[date.toString()] = 'test2';
obj[date]; // 'test2', because JavaScript converts object keys to strings
The Map Constructor
The Map
constructor takes a single parameter iterable
. In practice, iterable
is usually an array of key/value pairs [[key1, value1], [key2, value2]]
. However, you can also pass a map to the Map
constructor.
const date = new Date('2019-06-01');
const map1 = new Map([
['answer', 42],
[date, 'test1']
]);
map1.get('answer'); // 42
map1.get(date); // test1
// If you pass `map1` to the Map constructor, JavaScript will create a
// copy of `map1`
const map2 = new Map(map1);
map2.get('answer'); // 42
map2.get(date); // test1
map2.set('hello', 'world');
map1.get('hello'); // undefined
You cannot pass an object to the map constructor. To convert an object to a map, you must use the Object.entries()
function to convert the object to an array of key/value pairs.
const obj = { answer: 42 };
// This throws an error because objects are **not** iterable
// "TypeError: undefined is not a function"
new Map(obj);
// Works, you need to use `Object.entries()` to convert the object
// to a key/value array
const map = new Map(Object.entries(obj));
map.get('answer'); // 42
Iterating Over a Map
You can iterate over a map's keys or key/value pairs using a for/of
loop. Maps have a keys()
function that gives you the map's keys, and an entries()
function that gives you the map's key/value pairs.
const map = new Map([
['key1', 1],
['key2', 2],
['key3', 3]
]);
for (const key of map.keys()) {
// 'key1', 'key2', 'key3'
key;
}
for (const [key, value] of map.entries()) {
// 'key1', 'key2', 'key3'
key;
// 1, 2, 3
value;
}