Map is is a special type collection, like an object with keys of any data type. Object vs Map
let john = { name: "John" };
let obj = {};
obj[john] = 123;
obj // {[object Object]: 123}
let map = new Map();
map.set(john, 123);
map // [key: {name: "John"}, value: 123]
Declaration new Map([iterable])
let map = new Map() // creates the map
// or
let map = new Map([
['1', 'str1'],
[1, 'num1'],
[true, 'bool1']
]);
Add map.set(key, value)
map.set('1', 'str1') // a string key
map.set(1, 'num1') // a numeric key
map.set(true, 'bool1') // a boolean key
Get map.get(key) returns the value by the key undefined if key doesn’t exist in map map[key] - works, but isn’t the right way
map.get('1'); // 'str1'
map.get(1); // 'num1'
Size
map.size; // 3
Delete map.delete(key) - removes the value by the key map.clear() - removes everything from the map Has map.has(key) - returns true if the key exists, false otherwise Iteration Iteration goes in the same order as the values were inserted
let recipeMap = new Map([
['cucumber', 500],
['tomatoes', 350],
['onion', 50]
]);
// returns iterable of keys, values & entries
recipeMap.keys() // MapIterator {"cucumber", "tomatoes", "onion"}
recipeMap.values() // MapIterator{500, 350, 50}
recipeMap.entries() // MapIterator{"cucumber" => 500, "tomatoes" => 350, "onion" => 50} // it’s used by default in for..of.
for (let key of recipeMap.keys()) alert(key) // cucumber, tomatoes, onion
for (let value of recipeMap.values()) alert(value) // 500, 350, 50
for (let entry of recipeMap) alert(entry) // cucumber,500 (and so on) // the same as of recipeMap.entries()
recipeMap.forEach( (value, key, map) => {
alert(`${key}: ${value}`) // cucumber: 500 etc
})
Chaining map.set call returns the map itself
map.set('1', 'str1').set(1, 'num1').set(true, 'bool1')
map // Map(3){'1' => 'str1', 1 => 'num1', true => 'bool1'}
Array--> Map
let map = new Map([
['1', 'str1'],
[1, 'num1'],
[true, 'bool1']
]);
map.get('1') // "str1"
Object--> Map
let obj = {
name: "John",
age: 30
};
let map = new Map(Object.entries(obj));
map.get('name') // "John"
Map--> Object
let prices = Object.fromEntries([
['banana', 1],
['orange', 2],
])
prices // { banana: 1, orange: 2, meat: 4 }
WeakMap allows only objects as keys removes them together with associated value once they become inaccessible main advantages are that they have weak reference to objects they can easily be removed by garbage collector disadvantages are not having support for clear, size, keys, values… idea is that object key stays in map if we even delete the object reference, it is not garbage collected but in weakMap if we kill the obj it will be also removed from the weakMap If we’re working with an object that “belongs” to another code, maybe even a third-party library, and would like to store some data associated with it, that should only exist while the object is alive – then WeakMap is exactly what’s needed.
let map = new Map();
let obj1 = {name: "Jane"}
let obj2 = {name: "Anton"}
map.set(obj1, "good girl");
map.set(obj2, "good boy");
obj1 = null
obj2 = null
map.size // 2 // bad
let weakMap = new WeakMap();
let obj1 = {name: "Jane"}
let obj2 = {name: "Anton"}
weakMap.set(obj1, "good girl");
weakMap.set(obj2, "good boy");
obj1 = null
obj2 = null
weakMap.size // undefined
// When obj gets garbage collected, weakMap will be removed as well