JavaScript Map and WeakMap

ES6 introduced Map and WeakMap data types in JavaScript. These seem like regular JavaScript Objects but are more potent than an Object. Maps and WeakMap are data structures composed of a collection of key/value pairs.

Issues with Objects

Conversion of an object into maps converts the object key into a string.


var stu1 = { id: 1 },
stu2 = { id: 2 },
stu3 = { id: 3 };

var stuTotalPhoneNumbers = {};

stuTotalPhoneNumbers[stu1] = 2;
stuTotalPhoneNumbers[stu2] = 3;

console.log(`Student 1 have ${stuTotalPhoneNumbers[stu1]} numbers`); // 3
console.log(`Student 2 have ${stuTotalPhoneNumbers[stu2]} numbers`); // 3   

Strange! the console gives us 3 because both objects converted into the string "[object Object]". You can verify this using this snippet.


console.log(Object.keys(stuTotalPhoneNumbers));  // ['[object Object]']

So let us know how maps work.

JavaScript Map

A map is just like a regular javascript object with some extra features. So firstly we need to understand how we can create a Map data structure.

How to Create a Map


// Create a Map
var stuTotalPhoneNumbers = new Map([
  [stu1, 2],
  [stu2, 3],
]);

Here creation and setting of both operations are done by the Map constructor. But we can also set the map’s value using the set method.

The set method


// Create a Map
var stuTotalPhoneNumbers = new Map();

// Set Map Values
stuTotalPhoneNumbers.set(stu1, 2); // key - > stu1, value -> 2
stuTotalPhoneNumbers.set(stu2, 3); // key - > stu2, value -> 3

After creating and filling in the value of Map we need to get the map’s value. Here we can use the get method.

The get method


// Get Map values
console.log(stuTotalPhoneNumbers.get(stu1)); // 2
console.log(stuTotalPhoneNumbers.get(stu2)); // 3

So We use the get() and set() methods to access values in Maps. Sometimes we need to check whether a key exists or not so we will use has method

The has method

// Check key exist or not
console.log(stuTotalPhoneNumbers.has(stu1)); // true
console.log(stuTotalPhoneNumbers.has(stu3)); // false

The size property

// Get size of map
console.log(stuTotalPhoneNumbers.size); // 2

The delete method

// Delete key from map
stuTotalPhoneNumbers.delete(stu1);
console.log(stuTotalPhoneNumbers.has(stu1)); // false

The clear method

// Clear entire map
stuTotalPhoneNumbers.clear(); 
console.log(stuTotalPhoneNumbers.has(stu1)); // false
console.log(stuTotalPhoneNumbers.has(stu2)); // false

Map Type


// Using typeof
console.log(typeof stuTotalPhoneNumbers); // "object"

// Using instance
console.log(stuTotalPhoneNumbers instanceof Map); // true 

Map Iteration


var stuTotalPhoneNumbers = new Map([
      [stu1, 2],
      [stu2, 3],
      [stu3, 5]
 ]);

for (var [key, value] of stuTotalPhoneNumbers) {
    console.log(`${key} = ${value}`);
}

If maps are just like ordinary objects, then one question arises: where should we use a map and where should we use an object?

JavaScript Maps vs Objects

Map Object
Iterable Not iterable
Have size property Have not size property
Keys insert in order Keys have no order
The key can be any data type key only be a string

JavaScript WeakMap

WeakMap is a type of Map whose keys must be objects and also primitive data types, are not allowed as a key. It’s similar to the map with some differences so the set, get, has, and delete method works for Weakmap.

Primitive data types are not allowed


var stu1 = { id: 1 },
stu2 = { id: 2 },
stu3 = { id: 3 };

// Create a Map
var stuTotalPhoneNumbers = new WeakMap();

// Only Object Alowed as a key
stuTotalPhoneNumbers.set(stu1, 2); // key - > stu1, value -> 2
stuTotalPhoneNumbers.set(stu2, 3); // key - > stu2, value -> 3

// Not allowed case 
stuTotalPhoneNumbers.set("phonenumbers", 2); // key - > stu1, value -> 2

WeakMaps are not iterable

All available methods on WeakMap can access using an object as a key But WeakMaps are not iterable.


stuTotalPhoneNumbers.set(stu1, 2); // key - > stu1, value -> 2
stuTotalPhoneNumbers.set(stu2, 3); // key - > stu2, value -> 3

console.log(stuTotalPhoneNumbers.has(stu1)); // true
console.log(stuTotalPhoneNumbers.get(stu1)); // 2
console.log(stuTotalPhoneNumbers.has(stu2)); // true	

WeakMap good for Memory

It’s a very useful case of WeakMap. Let’s understand with an example.


var stu1 = {}; // stu1 occupy memory

var stuTotalPhoneNumbersMap = new Map();
stuTotalPhoneNumbers.set(stu1, 2); // We passed reference of stu1 object

var stuTotalPhoneNumbersWeakMap = new WeakMap();
stuTotalPhoneNumbersWeakMap.set(stu1, 2); // We passed reference of stu1 object

We have passed the reference of stu1 to the Map and WeakMap But suppose that the stu1 object remove.


stu1 = null; // dereference stu1 object

So what do you think will happen?


stuTotalPhoneNumbersMap.set(stu1, 4);
console.log(stuTotalPhoneNumbersMap.has(stu1));
console.log(stuTotalPhoneNumbersMap.get(stu1)); // set

console.log(stuTotalPhoneNumbersWeakMap.has(stu1));
console.log(stuTotalPhoneNumbersWeakMap.get(stu1));
stuTotalPhoneNumbersWeakMap.set(stu1, 4); // Error WeakMap key must be an object

// still we can get the value of stu1 object
console.log(stuTotalPhoneNumbersMap.keys().next().value);

// WeakMap does not have the .keys method

So it’s all about Map and WeakMap. For more details, you can reach out to MDN.

About the Author: Pankaj Bisht