This article illustrates the operations of JavaScript Map. Most of the content come from MDN.
About Map
The Map
object holds key-value pairs and remembers the original insertion order of the keys. It iterates its elements in insertion order — a for...of
loop returns an array of [key, value]
for each iteration.
- Key equality
NaN
is considered the same asNaN
(even thoughNaN !== NaN
) and all other values are considered equal according to the semantics of the===
operator.let myMap = new Map() myMap.set(NaN, 'not a number') myMap.get(NaN) // "not a number" let otherNaN = Number('foo') myMap.get(otherNaN) // "not a number"
Basic operations
Create
Use the Map()
constructor creates Map
objects.
Syntax:
new Map([iterable]);
// iterable can be an Array or other iterable objects whose elements are key-value pairs.
Examples:
let map1 = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);
let map2 = new Map();
map2.set(1, 'one');
map2.set(2, 'two');
map2.set(3, 'three');
Size
console.log(map1.size);
Loop
There are several ways to loop a Map object.
iterator or entries
The initial value of the @@iterator
property is the same function object as the initial value of the entries
method. The map iterator function, which is the entries()
function by default.
iterator:
const map1 = new Map();
map1.set('0', 'foo');
map1.set(1, 'bar');
const iterator1 = map1[Symbol.iterator]();
for (const item of iterator1) {
console.log(item);
}
// expected output: Array ["0", "foo"]
// expected output: Array [1, "bar"]
entries():
The entries()
method returns a new Iterator object that contains the [key, value]
pairs for each element in the Map
object in insertion order. In this particular case, this iterator object is also an iterable, so the for-of loop can be used.
const iterator1 = map1.entries();
for (const item of iterator1) {
console.log(item);
}
// expected output: Array ["0", "foo"]
// expected output: Array [1, "bar"]
for…of
let myMap = new Map();
myMap.set(0, 'zero');
myMap.set(1, 'one');
// -------- Loop key, value pairs
for (let [key, value] of myMap) {
console.log(key + ' = ' + value)
}
// 0 = zero
// 1 = one
// -------- Loop keys
for (let key of myMap.keys()) {
console.log(key)
}
// 0
// 1
// -------- Loop values
for (let value of myMap.values()) {
console.log(value)
}
// zero
// one
// -------- entries
for (let [key, value] of myMap.entries()) {
console.log(key + ' = ' + value)
}
// 0 = zero
// 1 = one
forEach
The forEach()
method executes a provided function once per each key/value pair in the Map
object, in insertion order.
function logMapElements(value, key, map) {
console.log(`m[${key}] = ${value}`);
}
new Map([['foo', 3], ['bar', {}], ['baz', undefined]])
.forEach(logMapElements);
// expected output: "m[foo] = 3"
// expected output: "m[bar] = [object Object]"
// expected output: "m[baz] = undefined"
Syntax
myMap.forEach(callback([value][, key][, map])[, thisArg])
Parameters
callback
Function to execute for each entry of
myMap
. It takes the following arguments:value
Optional. Value of each iteration.key
Optional. Key of each iteration.map
Optional. The map being iterated (myMap
in the above Syntax box).
thisArg
OptionalValue to use as
this
when executingcallback
.
Delete
- delete(), deletes the specified element.
- clear(), deletes all elements.
delete()
The delete(key)
method removes the specified element from a Map
object by key.
It returns true
if an element in the Map
object existed and has been removed, or false
if the element does not exist.
const map1 = new Map();
map1.set('bar', 'foo');
console.log(map1.delete('bar'));
// expected result: true
// (true indicates successful removal)
console.log(map1.has('bar')); // false
clear()
The clear()
method removes all elements from a Map
object.
const map1 = new Map();
map1.set('bar', 'baz');
map1.set(1, 'foo');
console.log(map1.size); // 2
map1.clear();
console.log(map1.size); // 0
get()
The get(key)
method returns a specified element from a Map
object. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map
object.
const map1 = new Map();
map1.set('bar', 'foo');
console.log(map1.get('bar')); // "foo"
console.log(map1.get('baz')); // undefined
has()
The has(key)
method returns a boolean indicating whether an element with the specified key exists or not.
const map1 = new Map();
map1.set('bar', 'foo');
console.log(map1.has('bar')); // true
console.log(map1.has('baz')); // false
set()
The set(key, value)
method adds or updates an element with a specified key and a value to a Map
object.
const map1 = new Map();
map1.set('bar', 'foo');
console.log(map1.get('bar')); // "foo"
map1.set('bar', 'foo2');
console.log(map1.get('bar')); // "foo2"
This is the only right way to update or add an element through set()
.
Note
It is possible to set properties of a Map like other generic objects, but this will cause considerable confusion. For these properties set in this way are not stored in the Map for queries. Other operations on the data fail:
let wrongMap = new Map() wrongMap['bla'] = 'blaa' wrongMap['bla2'] = 'blaaa2' console.log(wrongMap) // Map { bla: 'blaa', bla2: 'blaaa2' } // Other operations on the data fail. wrongMap.has('bla') // false wrongMap.delete('bla') // false console.log(wrongMap) // Map { bla: 'blaa', bla2: 'blaaa2' }
Members
entities()
The entries()
method returns a new Iterator object that contains the [key, value]
pairs for each element in the Map
object in insertion order. In this particular case, this iterator object is also an iterable, so the for-of loop can be used. When the protocol [Symbol.iterator]
is used, it returns a function that, when invoked, returns this iterator itself.
const map1 = new Map();
map1.set('0', 'foo');
map1.set(1, 'bar');
const iterator1 = map1.entries();
console.log(iterator1.next().value);
// expected output: ["0", "foo"]
console.log(iterator1.next().value);
// expected output: [1, "bar"]
keys()
The keys()
method returns a new Iterator object that contains the keys for each element in the Map
object in insertion order.
const map1 = new Map();
map1.set('0', 'foo');
map1.set(1, 'bar');
const iterator1 = map1.keys();
console.log(iterator1.next().value);
// expected output: "0"
console.log(iterator1.next().value);
// expected output: 1
values()
The values()
method returns a new Iterator object that contains the values for each element in the Map
object in insertion order.
const map1 = new Map();
map1.set('0', 'foo');
map1.set(1, 'bar');
const iterator1 = map1.values();
console.log(iterator1.next().value);
// expected output: "foo"
console.log(iterator1.next().value);
// expected output: "bar"
Other operations
Map and Array
Array to Map
It is easy to convert an Array to a Map, for Map()
constructor accepts an array as its parameter:
let kvArray = [['key1', 'value1'], ['key2', 'value2']];
// Use the regular Map constructor to transform a 2D key-value Array into a map
let myMap = new Map(kvArray);
Map to Array
To convert a Map to an Array:
let kvArray = [['key1', 'value1'], ['key2', 'value2']];
let myMap = new Map(kvArray);
// Use Array.from() to transform a map into a 2D key-value Array
let arr1 = Array.from(myMap);
console.log(arr1); // Will show you exactly the same Array as kvArray
// A succinct way to do the same, using the spread syntax
let arr2 = [...myMap];
console.log(arr2);
let arr3 = Array.from(myMap.keys());
console.log(arr3); // ["key1", "key2"]
Map and JSON
There is not direct support to convert a map to JSON, we can do that by using array.
Map to Json
let jsonStr = JSON.stringify([...myMap]);
// Or
let jsonStr2 = JSON.stringify(Array.from(myMap));
JSON to Map
let myMap = Map(JSON.parse(jsonStr));
Object vs Map
An object is similar to a map, both of them have a key-value structure. Objects vs Maps lists the differences between objects and a maps. Below are some main of them :
- Key type:
- Size:
- You need to get the item count of an object manually.
- Use
size
property to directly get size of a map.
- Iteration
- By default, Object does not implement an iteration protocol, it is not directly iterable using
for...of
statement (by default). The for…in statement allows you to iterate over the enumerable properties of an object. - A Map is iterable, it can be directly iterated.
- By default, Object does not implement an iteration protocol, it is not directly iterable using
- Performance
When it comes to scenarios involving frequent additions and removal:
- A map performs better.
Suggestions about object vs map
Object is much more than a Map, it shouldn’t be used just for the purpose of hashing if there exists another choice.