JavaScript Map
Learn about the JavaScript Map object including methods, use cases, and JavaScript Map vs Object.
Table of Contents 📖
What is a Map?
A JavaScript Map is an object that holds key-value pairs. What makes it unique is that it remembers the original insertion order of the keys, a key in the map can only occur once, and the keys and values can be anything such as an object, primitive type, etc.
Creating a Map
To create a JavaScript Map, we use the Map constructor.
const myMap = new Map();
We can store data in the Map by using the set method. The set method takes two arguments, the first is the key and the second is the value.
myMap.set('myKey', 'myVal');
We can retrieve data stored in the Map object with the get method, providing it the key we want the value for.
const myVal = myMap.get('myKey');
console.log(myVal); // myVal
If there is no value associated with a key then undefined is returned.
const myVal = myMap.get('noKeyFound');
console.log(myVal); // undefined
We can empty out a Map object by using the clear method.
myMap.clear();
console.log(myMap.size); // 0
The size property returns the number of key value pairs in the Map object. We can remove a specific key from the Map by using the delete method.
myMap.set('myKey2', 'myVal2');
myMap.set('myKey3', 'myVal3');
console.log(myMap.delete('myKey2')); // true
console.log(myMap.delete('myKey4')); // false
The delete method returns true if the element existed in the Map and has been removed, and false if the element does not exist. We can check if an element is contained in the Map object with the has method.
myMap.set('myKey2', 'myVal2');
myMap.set('myKey3', 'myVal3');
console.log(myMap.has('myKey2')); // true
console.log(myMap.has('myKey4')); // false
We can retrieve all the keys in the Map object with the keys method. The keys returned will be in insertion order.
myMap.set('myKey', 'myVal');
myMap.set('myKey2', 'myVal2');
myMap.set('myKey3', 'myVal3');
const myKeys = myMap.keys();
console.log(myKeys.next()); // { value: 'myKey', done: false }
console.log(myKeys.next()); // { value: 'myKey2', done: false }
console.log(myKeys.next()); // { value: 'myKey3', done: false }
console.log(myKeys.next()); // { value: undefined, done: true }
Specifically, what the keys method returns is an iterator object. An iterator object has a next method that returns an object containing the current value and a boolean signaling if the iterator has been completely iterated through or not. We can do the same thing with the Map object's values by using the values method.
myMap.set('myKey', 'myVal');
myMap.set('myKey2', 'myVal2');
myMap.set('myKey3', 'myVal3');
const myValues = myMap.values();
console.log(myValues.next()); // { value: 'myVal', done: false }
console.log(myValues.next()); // { value: 'myVal2', done: false }
console.log(myValues.next()); // { value: 'myVal3', done: false }
console.log(myValues.next()); // { value: undefined, done: true }
We can iterate over the Map object's keys and values by using the entries method.
myMap.set('myKey', 'myVal');
myMap.set('myKey2', 'myVal2');
myMap.set('myKey3', 'myVal3');
const myEntries = myMap.entries();
console.log(myEntries.next()); // { value: [ 'myKey', 'myVal' ], done: false }
console.log(myEntries.next()); // { value: [ 'myKey2', 'myVal2' ], done: false }
console.log(myEntries.next()); // { value: [ 'myKey3', 'myVal3' ], done: false }
console.log(myEntries.next()); // { value: undefined, done: true }
We can also use the forEach method.
myMap.set('myKey', 'myVal');
myMap.set('myKey2', 'myVal2');
myMap.set('myKey3', 'myVal3');
const myEntries = myMap.forEach((val, key, map) => {
console.log(val);
console.log(key);
console.log(map);
});
The forEach method takes a callback function where the first argument is the current value being iterated over, the second argument is the current key being iterated over, and the third argument is the Map object itself.
JavaScript Object vs Map
Both Maps and Objects are key value pairs where the value can be retrieved, keys can be deleted, etc. However, they are not identical and there are certain use cases where using a Map would be preferrable. First, a Map provides better security when setting keys and values.
const myMap = new Map();
myMap.set('toString', 'overriding toString');
console.log(myMap.toString()); // [object Map]
console.log(myMap.get('toString')); // overriding toString
const myObj = {};
myObj.toString = 'overriding to String';
console.log(myObj.toString()); // toString() is not a function
Here, if the provided key was toString and we were placing it in a JavaScript object then the toString method would be overwritten. However, if we were using a map it still works fine. Another difference is that the keys in a Map can be any value whereas in an Object the key must be either a String or a Symbol.
const myMap = new Map();
myMap.set(1, 'number one');
console.log(Array.from(myMap.keys())); // [1]
const myObj = {};
myObj[1] = 'number one';
console.log(Object.keys(myObj)); // ['1']
Above, notice how the Map preserved the type of the key as a number while the Object transformed the key into a String. There are a few other differences between the two.
- Maps perform better in scenarios where key value pairs are frequently added and removed.
- Maps always keep its keys in insertion order while this is not guaranteed with Objects.