Newsletter

The JavaScript Map object: methods, iteration and WeakMap

The JavaScript Map object: methods, iteration and WeakMap

Map is a constructor that gives you an easier and more efficient way of structuring and accessing data in a number of cases. 

Here is what a Map object really does, in three points:

  • A Map holds key-value pairs where the keys can be of any data type.

  • A Map remembers the original insertion order of the keys.

  • A Map has a property that holds its size.

Useful methods on the JavaScript Map object

  • clear() – removes every element from the map object.
  •  delete(key) – removes the element identified by the key. It returns true if the element was in the Map object, or false if it was not.
  •  entries() – returns a new Iterator object holding a [key, value] array for each element of the map object. The order of the entries in the Map object is the insertion order.
  •  forEach(callback[, thisArg]) – calls a callback for each key-value pair of the Map, in insertion order. The optional thisArg parameter sets the this value for each callback.
  •  get(key) – returns the value tied to the key. If the key does not exist, it returns undefined.
  •  has(key) – returns true if a value tied to the key exists, and false otherwise.
  •  keys() –  returns a new Iterator holding the keys of the elements in insertion order.
  •  set(key, value) – sets the value of the key in the map object. It returns the map object itself, so you can chain this method with others.
  •  values() returns a new iterator object holding the value of each element in insertion order.

Practical uses of the JavaScript Map object

Create a new Map object

Say you have a list of user objects like this one:

javascript
let pierre = {name: 'Pierre Lepez'},
    jean = {name: 'Jean Doe'},
    kevin = {name: 'Kévin Gomez'};

And say you need a Map object of users and roles. Here is the code for that:

javascript
let userRoles = new Map();

userRoles is an instance of Map, and its type is an object, as the following example shows:

javascript
console.log(typeof(userRoles)); // object
console.log(userRoles instanceof Map); // true

Add elements to a Map

To give a role to a user, use the set() method:

javascript
userRoles.set(kevin, 'admin');

The set() method ties the user kevin to the admin role. Since set() is chainable, you can save yourself some typing, as in this example:

javascript
userRoles.set(pierre, 'éditeur')
          .set(jean, 'abonné');

Initialise a Map object with an iterable

As mentioned earlier, you can pass an iterable object to the Map() constructor:

javascript
let userRoles = new Map([
    [kevin, 'admin'],
    [pierre, 'éditeur'],
    [jean, 'abonné']
]);

Getting an element by key

If you want to see Kévin’s role, use the get() method:

javascript
userRoles.get(kevin); // admin

If you pass a key that does not exist, the get() method returns undefined.

javascript
let foo = {name: 'Foo'};
userRoles.get(foo); //undefined

Check that an element exists, by key

To check whether a key exists in our Map object, use the has() method.

javascript
userRoles.has(foo); // false
userRoles.has(pierre); // true

Count the elements in our Map object

The size property returns the number of entries in the Map object.

javascript
console.log(userRoles.size); // 3

Iterate over the “keys” of your Map object

To get the keys of a Map object, use the keys() method. The keys() method returns a new iterator object holding the keys of the elements of the object.

The following example prints the name of every user in the userRoles map.

javascript
let kevin = { name: 'Kévin Feige' },
  pierre = { name: 'Pierre Rocher' },
  jean = { name: 'Jean Moulin' };

let userRoles = new Map([
    [kevin, 'admin'],
    [pierre, 'éditeur'],
    [jean, 'abonné']
]);

for (const user of userRoles.keys()) {
  console.log(user.name);
}

Output:

javascript
Kévin Feige
Pierre Rocher
Jean Moulin

Iterate over the values of your Map object

In the same way, you can use the values() method to get an iterator object holding the values of every element of your Map object:

javascript
let kevin = { name: 'Kévin Feige' },
  pierre = { name: 'Pierre Rocher' },
  jean = { name: 'Jean Moulin' };

let userRoles = new Map([
    [kevin, 'admin'],
    [pierre, 'éditeur'],
    [jean, 'abonné']
]);

for (const role of userRoles.values()) {
  console.log(role);
}

Output:

javascript
admin
éditeur
abonné

Iterate over the entries of your Map object

The entries() method returns an iterator object holding a [key,value] array for each element of the Map object:

javascript
let kevin = { name: 'Kévin Feige' },
  pierre = { name: 'Pierre Rocher' },
  jean = { name: 'Jean Moulin' };

let userRoles = new Map([
    [kevin, 'admin'],
    [pierre, 'éditeur'],
    [jean, 'abonné']
]);

for (const role of userRoles.entries()) {
  console.log(`${role[0].name}: ${role[1]}`);
}

To make the loop read more naturally, you can use destructuring:

javascript
let kevin = { name: 'Kévin Feige' },
  pierre = { name: 'Pierre Rocher' },
  jean = { name: 'Jean Moulin' };

let userRoles = new Map([
    [kevin, 'admin'],
    [pierre, 'éditeur'],
    [jean, 'abonné']
]);

userRoles.forEach((role, user) => console.log(`${user.name}: ${role}`));

As well as the for…of loop, you can use the forEach() method of the map object:

Turn the keys or the values of a Map into an array

Sometimes you would rather work with an array than with an iterable object, and that is where the spread operator comes in.

The following example turns the keys of every element into an array of keys:

javascript
var keys = [...userRoles.keys()];
console.log(keys);

Output:

javascript
[ { name: 'Kévin Feige' },
  { name: 'Pierre Rocher' },
  { name: 'Jean Moulin' } ]

And this one turns the values of the elements into an array:

javascript
let roles = [...userRoles.values()];
console.log(roles);

Output:

javascript
[ 'admin', 'éditeur', 'abonné' ]

Remove an element from its key

To remove an entry from your Map object, use the delete() method.

javascript
userRoles.delete(pierre);

Remove every element from a Map object

To remove every entry from the Map object, use the clear() method:

javascript
userRoles.clear();
console.log(userRoles.size); // 0

WeakMap

A WeakMap is similar to a Map, except that the keys of a WeakMap have to be objects. That means that when a reference to a key (an object) goes out of scope, the matching value is freed from memory automatically.

A WeakMap only has a subset of the methods of a Map object:

  • get(key)
  • set(key, value)
  • has(key)
  • delete(key)

Here are the main differences between a Map and a WeakMap:

  • The elements of a WeakMap cannot be iterated over.
  • You cannot clear every element in one go.
  • You cannot read the size of a WeakMap.

In this tutorial you have learned how to work with the JavaScript Map object and with the methods that make its entries easy to handle.

JavaScript

Damien Flandrin Web developer since 2010, creator of Gekkode and Email Impact. Every article is tested on a real project before publication. Contact
Newsletter

New tests, tutorials and projects, by e-mail.

Reproducible tests, versioned code, dated results. Never any spam.