Map and set, weakmap and weakset
Map
Very similar to an object, however, with object the only key that is allowed is a String. Map on the other hand allows keys of any type. Any type as it ANY type, even an object can be used as a key
new Map()
: Creates a new empty mapmap.set(key, value)
: Sets the key-value pair into the mapmap.get(key)
: Returns the value by thekey
, returnsundefined
ifkey
doesn't exist in mapmap.has(key)
: Returnstrue
if thekey
exists,false
otherwisemap.delete(key)
: Removes the key-value pair by thekey
map.clear()
: Removes everything from the mapmap.size
: Returns the total number of key-value pair
The way that Map
compares keys is roughly the same as ===
, but NaN
is considered to be equal to NaN
hence, even NaN
can be used as key as well!
Iteration over Map
Three ways of iterating over a map
map.keys()
: Returns an iterable for keysmap.values()
: Returns an iterable for valuesmap.entries()
: Returns an iterable for both key and value, this is the default forfor ... of
let recipeMap = new Map();
recipeMap.set('cucumber', 500)
.set('tomatoes', 350)
.set('onion', 50);
for (let vegs of recipeMap.keys()) {
console.log(vegs); // cucumber, tomatoes, onion
}
for (let amount of recipeMap.values()) {
console.log(amount); //500, 350, 50
}
for (let entry of recipeMap) {
console.log(entry) // [cucumber, 500], [tomatoes, 350], [onion, 50]
}
The iteration follows the insertion order, unlike object which doesn't preserve the insertion order in iteration.
Map from array
You can create a map from a 2D array like below:
let map = new Map([
['1', 'str1'],
[1, 'num1'],
[true, true]
])
Map from object
You can create a map from an object like below:
let obj = {
name: "john",
age: 30
}
let map = new Map(Object.entries(obj));
Object.entries(obj)
will return a 2D array where the 1D array will be the two key-value properties. Since all of the key in object are String the key will always be a String.
Object from Map
Object.fromEntries
does the opposite, it will create an object from a map. All of the key from the map will be converted to a String, because keep in mind that object can only take String as it's key, nothing else. The values will be kept as the same.
let map3 = new Map();
map3.set(1, "50");
map3.set("name", "Ricky");
map3.set("2", "Ricky");
let obj = Object.fromEntries(map3); // {"1": "50", "name": "Ricky", "2": "Ricky}.
Set
A set of unique values. There is no key-value pair mapping, Set
only contains the values, and the same value may only occur once.
new Set([iterable])
: To create a set, if theiterable
object is provided, it creates a set from those valuesset.add(value)
: Add value to the set, and return the set itselfset.delete(value)
: Remove the value, returnstrue
ifvalue
existed otherwisefalse
set.has(value)
:true
if it contains thevalue
false
otherwise.set.clear()
: Removes everything from the setset.size
: Returns the number of elements in the set
Set iteration
You can iterate over a set using same for ... of
loop.
set.keys()
: Return the iterable object for valuesset.values()
: This is the same asset.keys()
set.entries()
: Return iterable object with entries[value, value]
These method exists in order to be compatible with Map
if you decide to switch from one to the other.
WeakMap
With normal Map
the object that is mapped as the value will be kept in memory and so long as the Map
exists, the object will exist as well.
WeakMap
on the other hand is different in handling how the garbage collection work. It doesn't prevent garbage-collection of key objects like Map
does, hence their use cases are completely different.
Here is how WeakMap
works.
let weakmap = new WeakMap();
let obj = {};
weakmap.set(obj, "ok");
First of all, WeakMap
can only take object as the key, if you try to use a primitive like String or integer it will result in an error.
Then, if the object we used as the key have no other references to that object (excluding the one from WeakMap
) it will be removed from memory automatically.
let john = {name: "John"};
let weakmap = new WeakMap();
weakmap.set(john, "...");
john = null; // the object now lost the reference!
// john is now lost from memory, because WeakMap doesn't prevent garbage collection of key objects.
In addition, there are limited functionality to WeakMap
, there is no iteration, no way to get all keys or values from it.
It only supports set, get, delete, has
method like a normal map.
Use cases
One of the use cases for WeakMap
is for caching. The result from a function call associated with an object can be stored in a WeakMap
, future calls on the same object can reuse the same result. Then when you want to clean up the cache
, you can just delete the reference to the object and that result in WeakMap
cache will be automatically removed from memory since it gets garbage collected.
WeakSet
Behaves similarly, but you can only ad objects to WeakSet
no primitives. Again only supports add, has, delete
no way of doing iterations.
Used for a yes/no fact, say if an object is still being used somewhere else or not.
The object will also be removed from the WeakSet
once the object becomes inaccessible/unreachable.
No Comments