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.