Chuyển tới nội dung
Home » Map And Weakmap In Javascript | Sự Khác Biệt Map Và Weak Map

Map And Weakmap In Javascript | Sự Khác Biệt Map Và Weak Map

Map vs  WeakMap in Javascript

7 Answers

They both behave differently when a object referenced by their keys/values gets deleted. Lets take the below example code:


var map = new Map(); var weakmap = new WeakMap(); (function(){ var a = {x: 12}; var b = {y: 12}; map.set(a, 1); weakmap.set(b, 2); })()

The above IIFE is executed there is no way we can reference

{x: 12}

and

{y: 12}

anymore. Garbage collector goes ahead and deletes the key b pointer from “WeakMap” and also removes

{y: 12}

from memory. But in case of “Map”, the garbage collector doesn’t remove a pointer from “Map” and also doesn’t remove

{x: 12}

from memory.

Summary: WeakMap allows garbage collector to do its task but not Map.

References: http://qnimate.com/difference-between-map-and-weakmap-in-javascript/

  • 20Why is it not removed from memory? Because you can still reference it!

    map.entries().next().value // [{x:12}, 1]

    May 29, 2015 at 2:42
  • 8It’s not a self invoked function. It’s an immediately invoked function expression. benalman.com/news/2010/11/… Jul 21, 2015 at 14:53
  • then what’s a difference between weakmap and object Aug 12, 2016 at 15:37
  • 2@MuhammadUmer: object can only have string ‘keys’, while

    WeakMap

    can only have non-primitive keys (no strings or numbers or

    Symbol

    s as keys, only arrays, objects, other maps, etc.). Aug 28, 2016 at 5:41
  • 2@nnnnnn Yes that’s the difference, it’s still in the

    Map

    but not in the

    WeakMap

    Aug 2, 2017 at 9:58

Maybe the next explanation will be more clear for someone.


var k1 = {a: 1}; var k2 = {b: 2}; var map = new Map(); var wm = new WeakMap(); map.set(k1, 'k1'); wm.set(k2, 'k2'); k1 = null; map.forEach(function (val, key) { console.log(key, val); // k1 {a: 1} }); k2 = null; wm.get(k2); // undefined

As you see, after removing

k1

key from the memory we can still access it inside the map. At the same time removing

k2

key of WeakMap removes it from

wm

as well by reference.

That’s why WeakMap hasn’t enumerable methods like forEach, because there is no such thing as list of WeakMap keys, they are just references to another objects.

  • 14in the last line, of course, wm.get(null) will be undefined.– DaNeShAug 12, 2016 at 21:39
  • 9Better answer than copying and pasting from the mozilla site, kudos. Dec 4, 2016 at 13:03
  • 3in the

    forEach

    ,

    (key, val)

    should be actually be

    (val, key)

    Jan 20, 2017 at 2:11
  • 3unbelievable how an example that makes no sense get so many upvotes Jul 18, 2020 at 22:01
  • 1map.get(k1) would also return null Sep 5, 2022 at 15:03

From the very same page, section “Why Weak Map?”:

The experienced JavaScript programmer will notice that this API could be implemented in JavaScript with two arrays (one for keys, one for values) shared by the 4 API methods. Such an implementation would have two main inconveniences. The first one is an O(n) search (n being the number of keys in the map). The second one is a memory leak issue. With manually written maps, the array of keys would keep references to key objects, preventing them from being garbage collected. In native WeakMaps, references to key objects are held “weakly”, which means that they do not prevent garbage collection in case there would be no other reference to the object.

Because of references being weak, WeakMap keys are not enumerable (i.e. there is no method giving you a list of the keys). If they were, the list would depend on the state of garbage collection, introducing non-determinism.

[And that’s why they have no

size

property as well]

If you want to have a list of keys, you should maintain it yourself. There is also an ECMAScript proposal aiming at introducing simple sets and maps which would not use weak references and would be enumerable.

‐ which would be the “normal”

Map

s. Not mentioned at MDN, but in the harmony proposal, those also have

items

,

keys

and

values

generator methods and implement the

Iterator

interface.

  • so

    new Map().get(x)

    has about the same look-up time as reading a property from a plain object? May 5, 2018 at 18:41
  • 1@AlexanderMills I don’t see what this has to do with the question, but here is some data. In general, yes they are similar, and you should use the appropriate one. May 5, 2018 at 18:48
  • So my understanding is Map maintains an internal array to persist its key because of that array. Garbage collector is not able to refrain the reference. In WeekMap, it doesnt have a array where keys maintained so key with no reference can be garbage collected. May 17, 2018 at 12:03
  • @MohanRam A

    WeakMap

    still has an array (or other collection) of entries, it just tells the garbage collector that those are weak references. May 17, 2018 at 12:41
  • 1@MohanRam Check the second paragraph in the first quote in the answer May 17, 2018 at 12:45

Another difference (source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap):

Keys of WeakMaps are of the type Object only. Primitive data types as keys are not allowed (e.g. a Symbol can’t be a WeakMap key).

Nor can a string, number, or boolean be used as a

WeakMap

key. A

Map

can use primitive values for keys.


w = new WeakMap; w.set('a', 'b'); // Uncaught TypeError: Invalid value used as weak map key m = new Map m.set('a', 'b'); // Works

  • 7In case anyone wonders: I can imagine the reason behind this is: you can’t keep or pass references to primitive types. So the key in a WeakMap would be its only reference, ever. That way garbage collection wouldn’t be possible. I don’t know if weak references are impossible or just don’t make sense. But either way the key needs to be something that can be referenced weakly. Jan 8, 2016 at 14:00

From Javascript.info

Map — If we use an object as the key in a regular Map, then while the Map exists, that object exists as well. It occupies memory and may not be garbage collected.


let john = { name: "John" }; let array = [ john ]; john = null; // overwrite the reference // john is stored inside the array, so it won't be garbage-collected // we can get it as array[0]

Similar to that, if we use an object as the key in a regular Map, then while the Map exists, that object exists as well. It occupies memory and may not be garbage collected


let john = { name: "John" }; let map = new Map(); map.set(john, "..."); john = null; // overwrite the reference // john is stored inside the map, // we can get it by using map.keys()

WeakMap — Now, if we use an object as the key in it, and there are no other references to that object – it will be removed from memory (and from the map) automatically.


let john = { name: "John" }; let weakMap = new WeakMap(); weakMap.set(john, "..."); john = null; // overwrite the reference // john is removed from memory!


WeakMap

keys must be objects, not primitive values.


let weakMap = new WeakMap(); let obj = {}; weakMap.set(obj, "ok"); // works fine (object key) // can't use a string as the key weakMap.set("test", "Not ok"); // Error, because "test" is not an object

Why????

Let’s see below example.


let user = { name: "User" }; let map = new Map(); map.set(user, "..."); user = null; // overwrite the reference // 'user' is stored inside the map, // We can get it by using map.keys()

If we use an object as the key in a regular


Map

, then while the

Map

exists, that object exists as well. It occupies memory and may not be garbage collected.

WeakMap

is fundamentally different in this aspect. It doesn’t prevent garbage-collection of key objects.


let user = { name: "User" }; let weakMap = new WeakMap(); weakMap.set(user, "..."); user = null; // overwrite the reference // 'user' is removed from memory!

if we use an object as the key in it, and there are no other references to that object – it will be removed from memory (and from the map) automatically.


WeakMap

does not support iteration and methods keys(), values(), entries(), so there’s no way to get all keys or values from it.

WeakMap has only the following methods:

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

That is obvious as if an object has lost all other references (like ‘user’ in the code above), then it is to be garbage-collected automatically. But technically it’s not exactly specified when the cleanup happens.

The JavaScript engine decides that. It may choose to perform the memory cleanup immediately or to wait and do the cleaning later when more deletions happen. So, technically the current element count of a

WeakMap

is not known. The engine may have cleaned it up or not or did it partially. For that reason, methods that access all keys/values are not supported.

Note:- The main area of application for WeakMap is an additional data storage. Like caching an object until that object gets garbage collected.

WeapMap in javascript does not hold any keys or values, it just manipulates key value using a unique id and define a property to the key object.

because it define property to

key object

by method

Object.definePropert()

, key must not be primitive type.

and also because WeapMap does not contain actually key value pairs, we cannot get length property of weakmap.

and also manipulated value is assigned back to the key object, garbage collector easily can collect key if it in no use.

Sample code for implementation.


if(typeof WeapMap != undefined){ return; } (function(){ var WeapMap = function(){ this.__id = '__weakmap__'; } weakmap.set = function(key,value){ var pVal = key[this.__id]; if(pVal && pVal[0] == key){ pVal[1]=value; }else{ Object.defineProperty(key, this.__id, {value:[key,value]}); return this; } } window.WeakMap = WeakMap; })();

reference of implementation

  • 1To be clear, this implementation only half works. It won’t allow using the same object as key in multiple weak maps. It also does not work for frozen objects. And of course, it leaks the mapping to anybody who has a reference to the object. The first can be fixed using symbols, but not the latter two. Jul 12, 2020 at 16:13
  • @AndreasRossberg In this implementation I have added hardcoded

    id

    , but this should be unique by using something Math.random and Date.now(), etc. And by adding this dynamic id, the first point can be solved. Could you please provide me a solution for the last two points. Jul 13, 2020 at 5:16
  • The first problem is solved more elegantly by using symbols. The latter two cannot be solved within JS, which is why WeakMap has to be a primitive in the language. Jul 13, 2020 at 7:18

JavaScript provides many data structures for developers to choose from. Two of the most commonly used data structures in JavaScript are

Map

and

WeakMap

. Although both of these data structures have similar functionalities, there are some key differences that set them apart. In this article, we’ll explore these differences and help you choose the right data structure for your needs.

Understanding Maps

Maps are a type of data structure that allows developers to store key-value pairs. In other words, they allow you to associate values with keys in a way that’s easy to access and manipulate. Maps are similar to objects in JavaScript, but they have a few key differences. For example, Maps can use any value as a key, including objects and functions, whereas objects can only use strings or symbols as keys.

To create a Map, you can use the

Map()

constructor, like this:


const myMap = new Map();

You can also initialize a Map with key-value pairs using an array of arrays, like this:


const myMap = new Map([ ["key1", "value1"], ["key2", "value2"], ]);

Once you have a Map, you can add or update key-value pairs using the

set()

method, like this:


myMap.set("key3", "value3");

You can also retrieve values from a Map using the

get()

method, like this:


const value = myMap.get("key1");

Understanding WeakMaps

WeakMaps are similar to Maps in that they also allow you to store key-value pairs. However, they have some key differences that make them useful in different situations.

The most significant difference between WeakMaps and Maps is that WeakMaps only allow objects as keys, and those objects are held weakly. In other words, if there are no other references to an object used as a key in a WeakMap, that object will be garbage collected, and the corresponding value will be automatically removed from the WeakMap. This can be useful in situations where you want to associate data with an object that may be destroyed, like a DOM node.

To create a WeakMap, you can use the

WeakMap()

constructor, like this:


const myWeakMap = new WeakMap();

You can also initialize a WeakMap with key-value pairs using an object, like this:


const myObj = {}; const myWeakMap = new WeakMap([[myObj, "value"]]);

Once you have a WeakMap, you can add or update key-value pairs using the

set()

method, like this:


myWeakMap.set(myObj, "new value");

You can also retrieve values from a WeakMap using the

get()

method, like this:


const value = myWeakMap.get(myObj);

Differences Between Maps and WeakMaps

Now that we’ve covered the basics of Maps and WeakMaps, let’s explore the differences between these two data structures.

  1. Key Types: Maps can use any value as a key, including strings, numbers, objects, and functions. WeakMaps can only use objects as keys.
  2. Garbage Collection: Objects used as keys in WeakMaps are held weakly, which means they can be garbage collected if there are no other references to them. This can be useful for situations where you want to associate data with an object that may be destroyed, like a DOM node. Maps do not have this feature and will keep keys and values in memory until they are explicitly deleted.
  3. Iteration: Maps can be iterated over using methods like

    keys()

    ,

    values()

    , and

    entries()

    . WeakMaps do not have these methods because they are not enumerable. This means that you cannot iterate over a WeakMap to retrieve all of its keys or values.
  4. Size: Maps have a

    size

    property that returns the number of key-value pairs in the map. WeakMaps do not have a

    size

    property because the number of key-value pairs is not fixed and can change based on garbage collection.
  5. Performance: WeakMaps have additional garbage collection overhead, so they can be slower than Maps. If performance is a concern, Maps may be a better choice.

When to Use Maps

Maps are a good choice when you need to store key-value pairs and want to use any type of value as a key. Maps are also a good choice when you need to iterate over the keys or values in a predictable order, or when you need to get the number of key-value pairs in the map.

When to Use WeakMaps

WeakMaps are a good choice when you need to associate data with an object that may be destroyed, like a DOM node. WeakMaps are also useful when you want to avoid memory leaks and do not need to iterate over the keys or values in the map.

Conclusion

By understanding these differences, you can choose the right data structure for your needs and build better, more efficient JavaScript applications.

  • Trending Categories
  • Data Structure
  • Networking
  • RDBMS
  • Operating System
  • Java
  • MS Excel
  • iOS
  • HTML
  • CSS
  • Android
  • Python
  • C Programming
  • C++
  • C#
  • MongoDB
  • MySQL
  • Javascript
  • PHP
  • Physics
  • Chemistry
  • Biology
  • Mathematics
  • English
  • Economics
  • Psychology
  • Social Studies
  • Fashion Studies
  • Legal Studies
  • Selected Reading
  • UPSC IAS Exams Notes
  • Developer’s Best Practices
  • Questions and Answers
  • Effective Resume Writing
  • HR Interview Questions
  • Computer Glossary
  • Who is Who

What is the difference between Map and WeakMap in JavaScript?

Javascript


const myMap =


new


Map();


console.log(myMap);


myMap.set(


"info"


, { name:


"Sam"


, age: 36 });


console.log(myMap);


console.log(myMap.get(


"info"


));


console.log(


"check whether info is there or not - "


+ myMap.has(


"info"


));


console.log(


"The no.of elements in a Map are "


+ myMap.size);


myMap.


delete


"address"


);


myMap.


delete


"info"


);


console.log(myMap);


const map2 =


new


Map();


map2.set(


"name"


"Sam"


);


map2.set(


"age"


"36"


);


map2.forEach(


function


(value, key) {


console.log(key +


"- "


+ value);


});

Output

Map(0) {}
Map(1) { ‘info’ => { name: ‘Sam’, age: 36 } }
{ name: ‘Sam’, age: 36 }
check whether info is there or not – true
The no.of elements in a Map are 1
Map(0) {}
name- Sam
age- 36

WeakMap: In a Weak Map, every key can only be an object and function. It used to store weak object references. For better understanding, we take an example of WeakMap and its properties:

Example: This example shows the implementation of Map in Javascript.

Map vs  WeakMap in Javascript
Map vs WeakMap in Javascript

Advantages of Map:

Map object provided by ES6. A key of a Map may occur once, which will be unique in the map’s collection. There are slight advantages to using a map rather than an object.

  • Accidental Keys & Security: No default keys are stored, only contain what’s explicitly put into them. Because of that, it’s safe to use.
  • Key Types & Order: It can be any value as a key function, object anything. And the order is straightforward way in the order of entry insertion.
  • Size: Because of the size property a map can be easily retrieved.
  • Performance: Any operation can be performed on math so easily in a better way.
  • Serialization and parsing: We can create our own serialization and parsing support for Map by using JSON.stringify() and JSON.parse() methods.

Removing Elements

You can use the

clear()

and the

delete()

method to remove elements from a Map.

The

delete()

method returns

true

if a specified key/value pair exists and has been removed or else returns

false

. For example,


let map1 = new Map(); map1.set('info', {name: 'Jack', age: "26"}); // removing a particular element map1.delete('address'); // false console.log(map1); // Map {"info" => {name: "Jack", age: "26"}} map1.delete('info'); // true console.log(map1); // Map {}

The

clear()

method removes all key/value pairs from a Map object. For example,


let map1 = new Map(); map1.set('info', {name: 'Jack', age: "26"}); // removing all element map1.clear(); console.log(map1); // Map {}

JavaScript ES6 / ES2015 - [08] Set, Map, WeakSet and WeakMap
JavaScript ES6 / ES2015 – [08] Set, Map, WeakSet and WeakMap

Summary


WeakMap

is

Map

-like collection that allows only objects as keys and removes them together with associated value once they become inaccessible by other means.


WeakSet

is

Set

-like collection that stores only objects and removes them once they become inaccessible by other means.

Their main advantages are that they have weak reference to objects, so they can easily be removed by garbage collector.

That comes at the cost of not having support for

clear

,

size

,

keys

,

values


WeakMap

and

WeakSet

are used as “secondary” data structures in addition to the “primary” object storage. Once the object is removed from the primary storage, if it is only found as the key of

WeakMap

or in a

WeakSet

, it will be cleaned up automatically.

Lúc nào nên xài cái gì?

Không phải ngẫu nhiên mà Javascript ES6 bổ sung thêm WeakMap. Rõ ràng Map luôn có sự bất tiện khi sử dụng.

Rõ ràng có sự bất tiện khi sử dụng Map

Vấn đề memory có được dọn dẹp hay không đã là sự khác biệt map và weakmap. Vậy lúc nào ta nên dùng WeakMap?

  • Đầu tiên, ta cần một Map để chứa key-value. Tuy nhiên thời gian sử dụng chỉ gói gọn trong một vài dòng code. Tính toán, mapping xong lại không xài tới Map nữa -> Ưu tiên sử dụng WeakMap.
  • Keeping private data about a specific object and only giving access to it to people with a reference to the Map. A more ad-hoc approach is coming with the private-symbols proposal but that’s a long time from now. Đảm bảo an toàn cho dữ liệu, chỉ cho phép access đối với các đối tượng có tham chiếu và cần sử dụng tới WeakMap.

Chắc sẽ còn một vài trường hợp khác WeakMap trở nên hữu ích. Tui sẽ bổ sung cho mấy ông sau.

Map vs WeakMap in javascript - When to use Map vs WeakMap?
Map vs WeakMap in javascript – When to use Map vs WeakMap?

WeakMap

The first difference between

Map

and

WeakMap

is that keys must be objects, not primitive values:

Now, if we use an object as the key in it, and there are no other references to that object – it will be removed from memory (and from the map) automatically.


let john = { name: "John" }; let weakMap = new WeakMap(); weakMap.set(john, "..."); john = null; // overwrite the reference // john is removed from memory!

Compare it with the regular

Map

example above. Now if

john

only exists as the key of

WeakMap

– it will be automatically deleted from the map (and memory).


WeakMap

does not support iteration and methods

keys()

,

values()

,

entries()

, so there’s no way to get all keys or values from it.


WeakMap

has only the following methods:

Why such a limitation? That’s for technical reasons. If an object has lost all other references (like

john

in the code above), then it is to be garbage-collected automatically. But technically it’s not exactly specified when the cleanup happens.

The JavaScript engine decides that. It may choose to perform the memory cleanup immediately or to wait and do the cleaning later when more deletions happen. So, technically, the current element count of a

WeakMap

is not known. The engine may have cleaned it up or not, or did it partially. For that reason, methods that access all keys/values are not supported.

Now, where do we need such a data structure?

Định nghĩa

Map thì đã quá quen thuộc rồi

The


Map

object holds key-value pairs and remembers the original insertion order of the keys. Any value (both objects and primitive values) may be used as either a key or a value.

Đối tượng


Map

lưu cặp key-value (khoá – giá trị) theo thứ tự chèn vào của khoá. Bất kỳ giá trị nào (cả đối tượng (objects) và primitive values) đều có thể sử dụng làm key hoặc value.

WeakMap thì bản thân bao gồm 2 chữ. Weak và Map, hẳn là phải có cái gì đó “yếu hơn” rồi.

The


WeakMap

object is a collection of key/value pairs in which the keys are weakly referenced. The keys must be objects and the values can be arbitrary values.

Đối tượng WeakMap

là collection của các cặp key/value với các key được tham chiếu yếu ớt. Các key phải là đối tượng và các value có thể là bất kỳ giá trị nào.

Cả Map và WeakMap đều cho phép lưu trữ theo kiểu key-value. Key và uniques và một loạt Value đi kèm. Tuy nhiên vẫn tồn tại một số sự khác biệt map và weakmap.

Weak không có nghĩa là yếu. Chỉ “lỏng lẻo” hơn một vài điểm thôi

Map, Set, WeakMap & WeakSet in JavaScript - Real use case
Map, Set, WeakMap & WeakSet in JavaScript – Real use case

Examples

Using WeakMap


const wm1 = new WeakMap(); const wm2 = new WeakMap(); const wm3 = new WeakMap(); const o1 = {}; const o2 = function () {}; const o3 = window; wm1.set(o1, 37); wm1.set(o2, "azerty"); wm2.set(o1, o2); // a value can be anything, including an object or a function wm2.set(o2, undefined); wm2.set(wm1, wm2); // keys and values can be any objects. Even WeakMaps! wm1.get(o2); // "azerty" wm2.get(o2); // undefined, because that is the set value wm2.get(o3); // undefined, because there is no key for o3 on wm2 wm1.has(o2); // true wm2.has(o2); // true (even if the value itself is 'undefined') wm2.has(o3); // false wm3.set(o1, 37); wm3.get(o1); // 37 wm1.has(o1); // true wm1.delete(o1); wm1.has(o1); // false

Implementing a WeakMap-like class with a .clear() method


class ClearableWeakMap { #wm; constructor(init) { this.#wm = new WeakMap(init); } clear() { this.#wm = new WeakMap(); } delete(k) { return this.#wm.delete(k); } get(k) { return this.#wm.get(k); } has(k) { return this.#wm.has(k); } set(k, v) { this.#wm.set(k, v); return this; } }

Emulating private members

Developers can use a

WeakMap

to associate private data to an object, with the following benefits:

  • Compared to a

    Map

    , a WeakMap does not hold strong references to the object used as the key, so the metadata shares the same lifetime as the object itself, avoiding memory leaks.
  • Compared to using non-enumerable and/or

    Symbol

    properties, a WeakMap is external to the object and there is no way for user code to retrieve the metadata through reflective methods like

    Object.getOwnPropertySymbols

    .
  • Compared to a closure, the same WeakMap can be reused for all instances created from a constructor, making it more memory-efficient, and allows different instances of the same class to read the private members of each other.


let Thing; { const privateScope = new WeakMap(); let counter = 0; Thing = function () { this.someProperty = "foo"; privateScope.set(this, { hidden: ++counter, }); }; Thing.prototype.showPublic = function () { return this.someProperty; }; Thing.prototype.showPrivate = function () { return privateScope.get(this).hidden; }; } console.log(typeof privateScope); // "undefined" const thing = new Thing(); console.log(thing); // Thing {someProperty: "foo"} thing.showPublic(); // "foo" thing.showPrivate(); // 1

This is roughly equivalent to the following, using private fields:


class Thing { static #counter = 0; #hidden; constructor() { this.someProperty = "foo"; this.#hidden = ++Thing.#counter; } showPublic() { return this.someProperty; } showPrivate() { return this.#hidden; } } console.log(thing); // Thing {someProperty: "foo"} thing.showPublic(); // "foo" thing.showPrivate(); // 1

Associating metadata

A

WeakMap

can be used to associate metadata with an object, without affecting the lifetime of the object itself. This is very similar to the private members example, since private members are also modelled as external metadata that doesn’t participate in prototypical inheritance.

This use case can be extended to already-created objects. For example, on the web, we may want to associate extra data with a DOM element, which the DOM element may access later. A common approach is to attach the data as a property:


const buttons = document.querySelectorAll(".button"); buttons.forEach((button) => { button.clicked = false; button.addEventListener("click", () => { button.clicked = true; const currentButtons = [...document.querySelectorAll(".button")]; if (currentButtons.every((button) => button.clicked)) { console.log("All buttons have been clicked!"); } }); });

This approach works, but it has a few pitfalls:

  • The

    clicked

    property is enumerable, so it will show up in

    Object.keys(button)

    ,

    for...in

    loops, etc. This can be mitigated by using

    Object.defineProperty()

    , but that makes the code more verbose.
  • The

    clicked

    property is a normal string property, so it can be accessed and overwritten by other code. This can be mitigated by using a

    Symbol

    key, but the key would still be accessible via

    Object.getOwnPropertySymbols()

    .

Using a

WeakMap

fixes these:


const buttons = document.querySelectorAll(".button"); const clicked = new WeakMap(); buttons.forEach((button) => { clicked.set(button, false); button.addEventListener("click", () => { clicked.set(button, true); const currentButtons = [...document.querySelectorAll(".button")]; if (currentButtons.every((button) => clicked.get(button))) { console.log("All buttons have been clicked!"); } }); });

Here, only code that has access to

clicked

knows the clicked state of each button, and external code can’t modify the states. In addition, if any of the buttons gets removed from the DOM, the associated metadata will automatically get garbage-collected.

Caching

You can associate objects passed to a function with the result of the function, so that if the same object is passed again, the cached result can be returned without re-executing the function. This is useful if the function is pure (i.e. it doesn’t mutate any outside objects or cause other observable side effects).


const cache = new WeakMap(); function handleObjectValues(obj) { if (cache.has(obj)) { return cache.get(obj); } const result = Object.values(obj).map(heavyComputation); cache.set(obj, result); return result; }

This only works if your function’s input is an object. Moreover, even if the input is never passed in again, the result still remains forever in the cache. A more effective way is to use a

Map

paired with

WeakRef

objects, which allows you to associate any type of input value with its respective (potentially large) computation result. See the WeakRefs and FinalizationRegistry example for more details.

Use case: caching

Another common example is caching. We can store (“cache”) results from a function, so that future calls on the same object can reuse it.

To achieve that, we can use

Map

(not optimal scenario):


// 📁 cache.js let cache = new Map(); // calculate and remember the result function process(obj) { if (!cache.has(obj)) { let result = /* calculations of the result for */ obj; cache.set(obj, result); return result; } return cache.get(obj); } // Now we use process() in another file: // 📁 main.js let obj = {/* let's say we have an object */}; let result1 = process(obj); // calculated // ...later, from another place of the code... let result2 = process(obj); // remembered result taken from cache // ...later, when the object is not needed any more: obj = null; alert(cache.size); // 1 (Ouch! The object is still in cache, taking memory!)

For multiple calls of

process(obj)

with the same object, it only calculates the result the first time, and then just takes it from

cache

. The downside is that we need to clean

cache

when the object is not needed any more.

If we replace

Map

with

WeakMap

, then this problem disappears. The cached result will be removed from memory automatically after the object gets garbage collected.


// 📁 cache.js let cache = new WeakMap(); // calculate and remember the result function process(obj) { if (!cache.has(obj)) { let result = /* calculate the result for */ obj; cache.set(obj, result); return result; } return cache.get(obj); } // 📁 main.js let obj = {/* some object */}; let result1 = process(obj); let result2 = process(obj); // ...later, when the object is not needed any more: obj = null; // Can't get cache.size, as it's a WeakMap, // but it's 0 or soon be 0 // When obj gets garbage collected, cached data will be removed as well

Use Maps more and Objects less
Use Maps more and Objects less

Tham khảo

  • Javascript ES6 – Đôi điều thú vị có thể bạn chưa biết
  • WeakMap – MDN Web Docs
  • Difference between “Map” and “WeakMap” in JavaScript

Thank for your attention – Have a great day – Happy coding!

Bài viết gốc được đăng tải tại kieblog.vn

Có thể bạn quan tâm:

  • Thiết kế Messaging Service WhatsApp – P2
  • JavaScript Arrays và Objects thật ra không khác gì sách và báo
  • Review source code – What make it better?

Xem thêm xin việc it hấp dẫn trên TopDev

The JavaScript ES6 has introduced two new data structures, i.e

Map

and

WeakMap

.

Map is similar to objects in JavaScript that allows us to store elements in a key/value pair.

The elements in a Map are inserted in an insertion order. However, unlike an object, a map can contain objects, functions and other data types as key.

WeakMap Methods

WeakMaps have methods

get()

,

set()

,

delete()

, and

has()

. For example,


const weakMap = new WeakMap(); console.log(weakMap); // WeakMap {} let obj = {}; // adding object (element) to WeakMap weakMap.set(obj, 'hello'); console.log(weakMap); // WeakMap {{} => "hello"} // get the element of a WeakMap console.log(weakMap.get(obj)); // hello // check if an element is present in WeakMap console.log(weakMap.has(obj)); // true // delete the element of WeakMap console.log(weakMap.delete(obj)); // true console.log(weakMap); // WeakMap {}

Урок 13. JavaScript. Все о Map, Set, WeakMap, WeakSet с примерами
Урок 13. JavaScript. Все о Map, Set, WeakMap, WeakSet с примерами

WeakSet


WeakSet

behaves similarly:

  • It is analogous to

    Set

    , but we may only add objects to

    WeakSet

    (not primitives).
  • An object exists in the set while it is reachable from somewhere else.
  • Like

    Set

    , it supports

    add

    ,

    has

    and

    delete

    , but not

    size

    ,

    keys()

    and no iterations.

Being “weak”, it also serves as additional storage. But not for arbitrary data, rather for “yes/no” facts. A membership in

WeakSet

may mean something about the object.

For instance, we can add users to

WeakSet

to keep track of those who visited our site:


let visitedSet = new WeakSet(); let john = { name: "John" }; let pete = { name: "Pete" }; let mary = { name: "Mary" }; visitedSet.add(john); // John visited us visitedSet.add(pete); // Then Pete visitedSet.add(john); // John again // visitedSet has 2 users now // check if John visited? alert(visitedSet.has(john)); // true // check if Mary visited? alert(visitedSet.has(mary)); // false john = null; // visitedSet will be cleaned automatically

The most notable limitation of

WeakMap

and

WeakSet

is the absence of iterations, and the inability to get all current content. That may appear inconvenient, but does not prevent

WeakMap/WeakSet

from doing their main job – be an “additional” storage of data for objects which are stored/managed at another place.

Javascript


let map1 =


new


Map([


[1, 2],


[2, 3],


[4, 5]


]);


console.log(


"Map1"


);


console.log(map1);


let map2 =


new


Map([


"firstname"


"sumit"


],


"lastname"


"ghosh"


],


"website"


"geeksforgeeks"


]);


console.log(


"Map2"


);


console.log(map2);

Output

Map1
Map(3) { 1 => 2, 2 => 3, 4 => 5 }
Map2
Map(3) {
‘firstname’ => ‘sumit’,
‘lastname’ => ‘ghosh’,
‘website’ => ‘geeksforgeeks’
}

Example 2: This example adds elements to the map using set() method.

#33 Maps and Weak Maps | JavaScript Full Tutorial
#33 Maps and Weak Maps | JavaScript Full Tutorial

Insert Item to Map

After you create a map, you can use the

set()

method to insert elements to it. For example,


// create a set let map1 = new Map(); // insert key-value pair map1.set('info', {name: 'Jack', age: 26}); console.log(map1); // Map {"info" => {name: "Jack", age: 26}}

You can also use objects or functions as keys. For example,


// Map with object key let map2 = new Map(); let obj = {}; map2.set(obj, {name: 'Jack', age: "26"}); console.log(map2); // Map {{} => {name: "Jack", age: "26"}}

Description

Keys of WeakMaps must be garbage-collectable. Most primitive data types can be arbitrarily created and don’t have a lifetime, so they cannot be used as keys. Objects and non-registered symbols can be used as keys because they are garbage-collectable.

Why WeakMap?

A map API could be implemented in JavaScript with two arrays (one for keys, one for values) shared by the four API methods. Setting elements on this map would involve pushing a key and value onto the end of each of those arrays simultaneously. As a result, the indices of the key and value would correspond to both arrays. Getting values from the map would involve iterating through all keys to find a match, then using the index of this match to retrieve the corresponding value from the array of values.

Such an implementation would have two main inconveniences:

  1. The first one is an

    O(n)

    set and search (n being the number of keys in the map) since both operations must iterate through the list of keys to find a matching value.
  2. The second inconvenience is a memory leak because the arrays ensure that references to each key and each value are maintained indefinitely. These references prevent the keys from being garbage collected, even if there are no other references to the object. This would also prevent the corresponding values from being garbage collected.

By contrast, in a

WeakMap

, a key object refers strongly to its contents as long as the key is not garbage collected, but weakly from then on. As such, a

WeakMap

:

  • does not prevent garbage collection, which eventually removes references to the key object
  • allows garbage collection of any values if their key objects are not referenced from somewhere other than a

    WeakMap

A

WeakMap

can be a particularly useful construct when mapping keys to information about the key that is valuable only if the key has not been garbage collected.

But because a

WeakMap

doesn’t allow observing the liveness of its keys, its keys are not enumerable. There is no method to obtain a list of the keys. If there were, the list would depend on the state of garbage collection, introducing non-determinism. If you want to have a list of keys, you should use a

Map

.

Learn JavaScript In Arabic 2021 - #127 - Map Vs WeakMap
Learn JavaScript In Arabic 2021 – #127 – Map Vs WeakMap

Iterate Over Map Keys

You can iterate over the Map and get the key using the

keys()

method. For example,


let map1 = new Map(); map1.set('name', 'Jack'); map1.set('age', '27'); // looping through the Map for (let key of map1.keys()) { console.log(key) }

Output

name age

new Map()

In this we use

new Map()

constructor,

Example: In this example, a Map named

prices

is created to associate product names with their respective prices, allowing for efficient retrieval and management of price information.

// Creating a Map for product pricesconst prices = new Map([ [“Laptop”, 1000], [“Smartphone”, 800], [“Tablet”, 400] ]);

JavaScript map() method in 7 minutes! 🗺
JavaScript map() method in 7 minutes! 🗺

Map.set():

You can add elements to a Map with the

set()

method.

Example: In this example, the

Map.set()

method is employed to add product prices to the Map named

prices

.

// Creating a Map for product prices const prices = new Map(); // Using Map.set() to add product prices prices.set(‘Laptop’, 1000); prices.set(‘Smartphone’, 800); // The Map now contains { ‘Laptop’ => 1000, ‘Smartphone’ => 800 }

Example 1: In this example, we will create a basic map object

Differences between Map and WeakMap

The functional mechanism of Map and WeakMap is same but they have little differences.

1) A WeakMap accepts only objects as keys whereas a Map,in addition to objects, accepts primitive datatype such as strings, numbers etc.

2) WeakMap objects doesn’t avert garbage collection if there are no references to the object which is acting like a key. Therefore there is no method to retrieve keys in WeakMap, whereas in Map there are methods such as Map.prototype.keys() to get the keys.

3) There is no size property exists in WeakMap.

Jaina - Skill X3 Vẫn Là Một Ẩn Số
Jaina – Skill X3 Vẫn Là Một Ẩn Số

JavaScript WeakMap

The WeakMap is similar to a Map. However, WeakMap can only contain objects as keys. For example,


const weakMap = new WeakMap(); console.log(weakMap); // WeakMap {} let obj = {}; // adding object (element) to WeakMap weakMap.set(obj, 'hello'); console.log(weakMap); // WeakMap {{} => "hello"}

When you try to add other data types besides objects, WeakMap throws an error. For example,


const weakMap = new WeakMap(); // adding string as a key to WeakMap weakMap.set('obj', 'hello');

// throws error // TypeError: Attempted to set a non-object key in a WeakMap

Use case: caching

Another common example is caching. We can store (“cache”) results from a function, so that future calls on the same object can reuse it.

To achieve that, we can use

Map

(not optimal scenario):


// 📁 cache.js let cache = new Map(); // calculate and remember the result function process(obj) { if (!cache.has(obj)) { let result = /* calculations of the result for */ obj; cache.set(obj, result); return result; } return cache.get(obj); } // Now we use process() in another file: // 📁 main.js let obj = {/* let's say we have an object */}; let result1 = process(obj); // calculated // ...later, from another place of the code... let result2 = process(obj); // remembered result taken from cache // ...later, when the object is not needed any more: obj = null; alert(cache.size); // 1 (Ouch! The object is still in cache, taking memory!)

For multiple calls of

process(obj)

with the same object, it only calculates the result the first time, and then just takes it from

cache

. The downside is that we need to clean

cache

when the object is not needed any more.

If we replace

Map

with

WeakMap

, then this problem disappears. The cached result will be removed from memory automatically after the object gets garbage collected.


// 📁 cache.js let cache = new WeakMap(); // calculate and remember the result function process(obj) { if (!cache.has(obj)) { let result = /* calculate the result for */ obj; cache.set(obj, result); return result; } return cache.get(obj); } // 📁 main.js let obj = {/* some object */}; let result1 = process(obj); let result2 = process(obj); // ...later, when the object is not needed any more: obj = null; // Can't get cache.size, as it's a WeakMap, // but it's 0 or soon be 0 // When obj gets garbage collected, cached data will be removed as well

map, filter & reduce 🙏 Namaste JavaScript Ep. 19 🔥
map, filter & reduce 🙏 Namaste JavaScript Ep. 19 🔥

Iterate Over Map Values

You can iterate over the Map and get the values using the

values()

method. For example,


let map1 = new Map(); map1.set('name', 'Jack'); map1.set('age', '27'); // looping through the Map for (let values of map1.values()) { console.log(values); }

Output

Jack 27

Javascript


let map1 =


new


Map();


map1.set(


"first name"


"sumit"


);


map1.set(


"last name"


"ghosh"


);


map1.set(


"website"


"geeksforgeeks"


.set(


"friend 1"


"gourav"


.set(


"friend 2"


"sourav"


);


console.log(map1);


console.log(


"map1 has website ? "


map1.has(


"website"


));


console.log(


"map1 has friend 3 ? "


map1.has(


"friend 3"


));


console.log(


"get value for key website "


map1.get(


"website"


));


console.log(


"get value for key friend 3 "


map1.get(


"friend 3"


));


console.log(


"delete element with key website "


+ map1.


delete


"website"


));


console.log(


"map1 has website ? "


map1.has(


"website"


));


console.log(


"delete element with key website "


map1.


delete


"friend 3"


));


map1.clear();


console.log(map1);

Output

Map(5) {
‘first name’ => ‘sumit’,
‘last name’ => ‘ghosh’,
‘website’ => ‘geeksforgeeks’,
‘friend 1’ => ‘gourav’,
‘friend 2’ => ‘sourav’
}
map1 has website ? true
map1 has friend 3 ? false
get…

JavaScript Array Map Method Practice in 5 Minutes
JavaScript Array Map Method Practice in 5 Minutes

Use case: additional data

The main area of application for

WeakMap

is an additional data storage.

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.

We put the data to a

WeakMap

, using the object as the key, and when the object is garbage collected, that data will automatically disappear as well.


weakMap.set(john, "secret documents"); // if john dies, secret documents will be destroyed automatically

Let’s look at an example.

For instance, we have code that keeps a visit count for users. The information is stored in a map: a user object is the key and the visit count is the value. When a user leaves (its object gets garbage collected), we don’t want to store their visit count anymore.

Here’s an example of a counting function with

Map

:


// 📁 visitsCount.js let visitsCountMap = new Map(); // map: user => visits count // increase the visits count function countUser(user) { let count = visitsCountMap.get(user) || 0; visitsCountMap.set(user, count + 1); }

And here’s another part of the code, maybe another file using it:


// 📁 main.js let john = { name: "John" }; countUser(john); // count his visits // later john leaves us john = null;

Now,

john

object should be garbage collected, but remains in memory, as it’s a key in

visitsCountMap

.

We need to clean

visitsCountMap

when we remove users, otherwise it will grow in memory indefinitely. Such cleaning can become a tedious task in complex architectures.

We can avoid it by switching to

WeakMap

instead:


// 📁 visitsCount.js let visitsCountMap = new WeakMap(); // weakmap: user => visits count // increase the visits count function countUser(user) { let count = visitsCountMap.get(user) || 0; visitsCountMap.set(user, count + 1); }

Now we don’t have to clean

visitsCountMap

. After

john

object becomes unreachable, by all means except as a key of

WeakMap

, it gets removed from memory, along with the information by that key from

WeakMap

.

In this article, we will talk about the difference between Map and WeakMap which are introduced by ES6. Javascript object supports only one key object. For supporting multiple key objects, Then Map comes on this path.

Map: A Map is an unordered list of key-value pairs where the key and the value can be of any type like string, boolean, number, etc. For better understanding, we take an example of Map and its properties.

Example: This example shows the implementation of Map in Javascript.

Javascript


let map1 =


new


Map();


map1.set(


"FirstName"


"Shobhit"


);


map1.set(


"LastName"


"Sharma"


);


map1.set(


"website"


"GeeksforGeeks"


);


console.log(map1);

Output

Map(3) {
‘FirstName’ => ‘Shobhit’,
‘LastName’ => ‘Sharma’,
‘website’ => ‘GeeksforGeeks’
}

Example 3: This example explains the use of Map methods like has(), get(), delete(), and clear().

Bạn đang ở đâu trong các Level của Lập Trình Viên? Level cuối cùng là thật sự tôi không biết!
Bạn đang ở đâu trong các Level của Lập Trình Viên? Level cuối cùng là thật sự tôi không biết!

Sự khác biệt Map và Weak Map

2.1 Key Store

Cùng là cơ chế lưu trữ key-value. Nhưng có sự khác biệt rõ ràng về tiêu chuẩn của key.

A WeakMap accepts only objects as keys whereas a Map,in addition to objects, accepts primitive datatype such as strings, numbers etc.

WeakMap chỉ chấp nhận kiểu objects đóng vai trò như là key. Trong khi Map, ngoài kiểu Objects, nó còn chấp nhận cả các kiểu nguyên thủy như Strings, Numbers,…

map.set(44, 12); // Lỗi weakmap.set(44, 13); // Lỗi. Không thể tạo WeakMap từ 2D array. var map_1 = new WeakMap([[1, 2], [4, 5]]);

Mà cái thằng WeakMap này cũng dị. Mấy function hay methods dùng được với map thì không dùng được với Weakmap.

console.log(weakmap.size); //undefined //loop through the keys in an map for(var i of map) { console.log(i); } //loop through the keys in an weakmap doesn’t work for(var i of weakmap) { console.log(i); } //delete all keys map.clear(); weakmap.clear(); //but this works

Ngoài chuyện Primitive Type thì còn một vấn đề khác nữa là Memory Leak. Cái này là “cốt lõi”. Có nó mới có chữ Weak trong WeakMap. Khác biệt cốt lõi nhất!

2.2 Vấn đề Memory Leak

Memory thì từ xưa đến nay đã luôn là vấn đề cố hữu của Map. Một Map được tạo ra cũng đồng nghĩa với một phần memory được cấp phát. Cấp thì dễ, nhưng đôi khi mấy anh dev lại quên lấy lại phần đó (mặc dù đã sử dụng xong Map).

Sự khác biệt giữa Map và WeakMap lại là vấn đề này. Đây cũng là điểm khác biệt cần nắm rõ để có lựa chọn sáng suốt khi lựa chọn Map hay WeakMap.

Để dễ hiểu hơn thì ta có thể xem xét ví dụ sau:

JavaScript

var map = new Map(); var weakmap = new WeakMap(); (function(){ var a = {x: 12}; var b = {y: 12}; map.set(a, 1); weakmap.set(b, 2); })()

Xét như ví dụ phía trên, function tóm gọn lại từ dòng 4 đến dòng 10. Tuy nhiên để access được b = {y: 12}; bên ngoài function scope thực sự là không thể.

Mặc dù cả Map và Weakmap đều là global access variable. Tuy nhiên cơ chế của WeakMap cho phép Garbage collector xóa pointer tới b của chính nó. Bản thân chữa weak mang nghĩa là yếu, liên kết của weak map tới chính đứa con mà nó set vào là liên kết lỏng lẻo.

So “Map” can cause more garbages in memory. We can say that “Map” references are strong pointer whereas “WeakMap” references are weak pointers.

Chính vì vậy Map có thể chiếm dụng khá nhiều về mặt memory. Cũng có thể nói “map” tham chiếu mạnh hơn so với “WeakMap”. Tham chiếu ở đây được hiểu là tham chiếu tới memory được cấp phát.

Summary


WeakMap

is

Map

-like collection that allows only objects as keys and removes them together with associated value once they become inaccessible by other means.


WeakSet

is

Set

-like collection that stores only objects and removes them once they become inaccessible by other means.

Their main advantages are that they have weak reference to objects, so they can easily be removed by garbage collector.

That comes at the cost of not having support for

clear

,

size

,

keys

,

values


WeakMap

and

WeakSet

are used as “secondary” data structures in addition to the “primary” object storage. Once the object is removed from the primary storage, if it is only found as the key of

WeakMap

or in a

WeakSet

, it will be cleaned up automatically.

In this tutorial, we will learn about JavaScript WeakMap and WeakSet objects. WeakMap and WeakSet are two new data structures introduced to JavaScript in ES6. These data structures provide a way to store data in a memory-efficient way and are useful for working with large datasets. We will discuss their features, use cases, and how to use them in your code.

The WeakMap object is a collection of key/value pairs in which the keys are objects and the values can be arbitrary values. It is similar to Map, but it only allows objects as keys and the keys are held weakly. This means that if there is no other reference to the key object, the entry in the WeakMap can be garbage collected. WeakMap is a perfect fit for private properties in JavaScript.

WeakMap objects are collections of key/value pairs in which the keys are objects and the values can be arbitrary values. The key difference between WeakMap and Map is that the keys in WeakMap are held weakly. This means that if there is no other reference to the key object, the entry in the WeakMap can be garbage collected.

WeakMap objects have some advantages over Map objects. For example, they are not enumerable, so you can’t use the for…in loop to iterate over the values in a WeakMap. This makes them useful for storing private data, as they can’t be enumerated or accessed by other code.

WeakMap objects also have the advantage of being able to store weak references to objects. This means that if there is no other reference to the object, the entry in the WeakMap can be garbage collected. This makes WeakMap objects ideal for storing private data, as the data will be automatically cleaned up when there are no other references to it.

To create a WeakMap, you can use the new keyword. To add items to the WeakMap, you can use the set() method, which takes two arguments: the key and the value.


let weakMap = new WeakMap(); let key = {}; let value = 'value'; weakMap.set(key, value);

You can also use the get() method to retrieve the value associated with a given key.


let weakMap = new WeakMap(); let key = {}; let value = 'value'; weakMap.set(key, value); let retrievedValue = weakMap.get(key); console.log(retrievedValue); // 'value'

The main difference between WeakMap and Map is that the keys in WeakMap are held weakly. This means that if there is no other reference to the key object, the entry in the WeakMap can be garbage collected. This makes WeakMap objects ideal for storing private data, as the data will be automatically cleaned up when there are no other references to it.

Another difference between WeakMap and Map is that WeakMap objects are not enumerable. This means that you can’t use the for…in loop to iterate over the values in a WeakMap. This makes them useful for storing private data, as they can’t be enumerated or accessed by other code.

Finally, WeakMap objects are not iterable, so you can’t use the for…of loop to iterate over the values in a WeakMap. This makes them useful for storing private data, as they can’t be iterated or accessed by other code.

To learn more about weakmap, visit .

A WeakSet is a special type of collection that allows you to store weakly held objects. This means that the objects stored in a WeakSet can be garbage collected if there are no other references to them. WeakSets are useful for keeping track of objects that need to be removed from memory when they are no longer needed.

A WeakSet is similar to a Set, with the main difference being that it only stores objects, not primitive values. Also, unlike a Set, a WeakSet does not have a size property, and its entries cannot be iterated over. This makes WeakSets more memory-efficient than Sets.

WeakSets are useful for keeping track of objects that need to be removed from memory when they are no longer needed. For example, a WeakSet could be used to keep track of objects that have been marked as “garbage” and should be removed when no longer needed. WeakSets are also useful for keeping track of objects that are in a “temporary” state, such as objects that have been created for a short period of time and no longer need to be kept in memory.

To create a WeakSet, you can use the WeakSet constructor, which takes an iterable (an array or other iterable object) of objects as its argument. The WeakSet constructor will add each object in the iterable to the WeakSet.


let myWeakSet = new WeakSet([{a:1}, {b:2}, {c:3}]);

Once a WeakSet is created, you can add objects to it using the add() method. This method takes an object as its argument and adds it to the WeakSet.


let myWeakSet = new WeakSet([{a:1}, {b:2}, {c:3}]); let obj = {d:4}; myWeakSet.add(obj); console.log(myWeakSet);

You can also remove objects from a WeakSet using the delete() method. This method takes an object as its argument and removes it from the WeakSet.


let myWeakSet = new WeakSet([{a:1}, {b:2}, {c:3}]); let obj = {b:2}; myWeakSet.delete(obj); console.log(myWeakSet);

Finally, you can check if an object is in a WeakSet using the has() method. This method takes an object as its argument and returns true if the object is in the WeakSet, or false if it is not.


let myWeakSet = new WeakSet([{a:1}, {b:2}, {c:3}]); let obj = {b:2}; console.log(myWeakSet.has(obj));

To learn more about weakset, visit .

JavaScript map is a collection of elements where each element is stored as a Key, value pair. Map objects can hold both objects and primitive values as either key or value. When we iterate over the map object returns the key, and value pair in the same order as inserted. Map() constructor is used to create Map in JavaScript.

JavaScript Map has a property that represents the size of the map.

Example:

Input:let map1 = new Map([ [1 , 10], [2 , 20] , [3, 30],[4, 40] ]);console.log(“Map1: “);console.log(map1);Output:// Map1: // Map(4) { 1 => 10, 2 => 20, 3 => 30, 4 => 40 }

Map Live User Location using Leaflet.js and OpenStreetMap - JavaScript Tutorial
Map Live User Location using Leaflet.js and OpenStreetMap – JavaScript Tutorial

Instance properties

These properties are defined on

WeakMap.prototype

and shared by all

WeakMap

instances.


WeakMap.prototype.constructor

The constructor function that created the instance object. For


WeakMap

instances, the initial value is the

WeakMap

constructor.


WeakMap.prototype[@@toStringTag]

The initial value of the


@@toStringTag

property is the string

"WeakMap"

. This property is used in

Object.prototype.toString()

.

WeakMap

In the below example we can find that WeakMap accepts only objects but not any primitive values (strings, numbers)

Example

Output

true fourth true

Kickstart Your Career

Get certified by completing the course

Get Started

Bài viết được sự cho phép của tác giả Kiên Nguyễn

Sự khác biệt map và weakmap luôn là một phần kiến thức cần nắm vững đối với lập trình viên Javascript. Nắm rõ sự khác biệt còn phải hiểu lúc nào nên sử dụng loại nào nữa. Đấy, vô vàn vấn đề cần tìm hiểu.

Tuy nhiên, khó cũng phải hiểu. Vì Data Structure không phải muốn dùng sao cũng được. Ở các System lớn, chỉ cần thay đổi một kiểu của DS thôi cũng gây ra hàng tá vấn đề.

Dữ liệu lớn, request xử lý hàng đống. Memory là thứ cần kiểm soát chặt chẽ để đảm bảo hệ thống luôn vận hành trơn tru. Kieblog hân hạnh giới thiệu bài viết sự khác biệt map và weakmap. Bắt đầu ngay thôi nào!

Tuyển dụng lập trình viên Javascript cho bạn

Phỏng vấn siêu tốc JavaScript, React và thuật toán
Phỏng vấn siêu tốc JavaScript, React và thuật toán

Get Key/Values of Map

You can iterate over the Map and get the key/value of a Map using the

entries()

method. For example,


let map1 = new Map(); map1.set('name', 'Jack'); map1.set('age', '27'); // looping through the Map for (let elem of map1.entries()) { console.log(`${elem[0]}: ${elem[1]}`); }

Output

name: Jack age: 27

Javascript


const myweakMap =


new


WeakMap();


console.log(myweakMap);


let obj = {};


myweakMap.set(obj,


'hello everyone'


);


console.log(myweakMap);


console.log(


"The element of a WeakMap - "


+ myweakMap.get(obj));


console.log(


"check if an element is present in WeakMap - "


+ myweakMap.has(obj));


console.log(


"deleting the element of WeakMap - "


+ myweakMap.


delete


(obj));


console.log(myweakMap);


const weakMap1 =


new


WeakMap();


console.log(weakMap1);


let obj1 = {};


weakMap.set(obj1,


'hello'


);


for


(let i of weakMap1) {


console.log(i);

Output:

WeakMap {

}
WeakMap {

}
The element of a WeakMap – hello everyone
check if an element is present in WeakMap – true
deleting the element of WeakMap – true
WeakMap {

}
WeakMap {

}
ReferenceError: weakMap is not defined



Difference between Map and WeakMap:

Map

WeakMap

A Map is an unordered list of key-value pairs where the key and the value can be of any type like string, boolean, number, etc. In a Weak Map, every key can only be an object and function. It used to store weak object references.
Maps are iterable. WeakMaps are not iterable.
Maps will keep everything even if you don’t use them. WeakMaps holds the reference to the key, not the key itself.
The garbage collector doesn’t remove a key pointer from “Map” and also doesn’t remove the key from memory. The garbage collector goes ahead and removes the key pointer from “WeakMap” and also removes the key from memory. WeakMap allows the garbage collector to do its task but not the Map.
Maps have some properties : .set, .get, .delete, .size, .has, .forEach, Iterators. WeakMaps have some properties : .set, .get, .delete, .has.
You can create a new map by using a new Map(). You can create a new WeakMap by using a new WeakMap().

Whether you’re preparing for your first job interview or aiming to upskill in this ever-evolving tech landscape, GeeksforGeeks Courses are your key to success. We provide top-quality content at affordable prices, all geared towards accelerating your growth in a time-bound manner. Join the millions we’ve already empowered, and we’re here to do the same for you. Don’t miss out – check it out now!

Looking for a place to share your ideas, learn, and connect? Our Community portal is just the spot! Come join us and see what all the buzz is about!

Last Updated :
17 Apr, 2023

Like Article

Save Article

Share your thoughts in the comments

Please Login to comment…

Đôi điều về Map, WeakMap trong Js

Bài đăng này đã không được cập nhật trong 5 năm

Trong lập trình thì bất kỳ ngôn ngữ nào bạn cũng phải trải qua xử lý các dữ liệu. Bài viết sẽ giới thiệu về Map và WeakMap kèm ứng dụng của chúng để có thể giúp bạn hiểu và có thể đâu đó áp dụng vào code của bạn để giải quyết vấn đề trơn tru hơn. Map: 1 key đi với 1 value Với Js thì bạn có thể thể hiện cấu trúc này qua object


const dict = { company: 'Framgia', Title: 'We made it awesome', } console.log(dict['company']) // Framgia

Với việc dùng object thì có thể chuỗi lấy dùng làm khóa


const obj = { foobar: 2 } const dict = new Map() dict .set('foo', 123) .set(obj, 'hello framgia') dict.get('foo') // 123 dict.get(obj) // 'hello framgia' // get value một khóa không tồn tại dict.get('bar') // undefined

Ở đây chúng ta có thể truyền vào constructor của Map một array với cặp value dạng [key, value]:


const dict = new Map([ ['foo', 123], [obj, 'hello framgia'] ])

Chúng ta có thể dùng bất kỳ kiểu dữ liệu để làm khóa cho Map (array, object, funtion or NaN).


const arr = [1] const f = () => {} dict .set(arr, 'array') .set(f, 'function') .set(NaN, 'not a number')

Để tìm key và value tương ứng trong Map ta dùng SameValueZero. SameValueZero mang ý nghĩa giống với === nhưng xem value của NaN là bằng nhau. SameValueZero sẽ nhận biết 2 object khác nhau sẽ là hai khóa riêng biệt


const bar = {} const foo = {} dict.set(bar, 'bar').set(foo, 'foo') dict.get(foo) // foo dict.get({}) // undefined

Khi map đã tồn tại key thì dữ liệu mới sẽ ghi đè lên.


const cst = new Map() cst.set('bar', 1000001) cst.set('bar', 1000002) cst.get('bar') // 1000002

Vậy làm thế nào để duyệt qua Map? Chúng ta sẽ dùng:


const dict = new Map([ ['key1', 96], ['key2', 69] ]) dict.keys() // ['key1', 'key2'] dict.values() // [96, 69] dict.entries() // [ ['key1', 96], ['key2', 69] ] dict.forEach(function(value, key, map) { console.log(`${key} has ${value}`) }, /* thisArgs bạn có thể truyền vào tham chiếu cho `this`/) // Sử dụng for..of for (let [key, value] of dict) { console.log(`${key} has ${value}`) }

Thao tác khác với Map:


const dict = new Map([ ['key1', 121], ['key', 212] ]) // Đếm số cặp giá trị trong map dict.size // 2 // Kiểm tra trong map có khóa "foo" hay không dict.has('key1') // true dict.has('foo') // false // Xóa một khóa, trả về true nếu thành công, false nếu thất bại dict.delete('foo') // false dict.delete('key2') // true // Xóa hết các cặp giá trị của map dict.clear()

WeakMap: có phương thức tương tự như Map, chỉ khác ở chổ bạn không thể duyệt WeakMap bằng phương thức .key() và .values(), .entries() và for..of với một lý do rất được quan tâm đó là “bảo toàn dữ liệu”. với WeakMap thì dữ liệu sẽ là private tức là bảo mật nhưng lại không gây rò rỉ bộ nhớ.


const weakMap = new WeakMap() class User { constructor() { const data = { cellPhone: 0905999999 } weakMap.set(this, data) } getCellPhone() { const data = privates.get(this) return data.cellPhone } } const user = new User() console.log(user) // {} console.log(user.getCellPhone()) // 0905999999

Map có những cải tiến hơn so với object, Map là công cụ hữu hiệu giúp lưu trữ dự liệu theo dạng (key, value). Tham khảo: 1 WeakMap for JavaScript Private Data – Steve Brownlee

All rights reserved

WeakMap

A

WeakMap

is a collection of key/value pairs whose keys must be objects or non-registered symbols, with values of any arbitrary JavaScript type, and which does not create strong references to its keys. That is, an object’s presence as a key in a

WeakMap

does not prevent the object from being garbage collected. Once an object used as a key has been collected, its corresponding values in any

WeakMap

become candidates for garbage collection as well — as long as they aren’t strongly referred to elsewhere. The only primitive type that can be used as a

WeakMap

key is symbol — more specifically, non-registered symbols — because non-registered symbols are guaranteed to be unique and cannot be re-created.


WeakMap

allows associating data to objects in a way that doesn’t prevent the key objects from being collected, even if the values reference the keys. However, a

WeakMap

doesn’t allow observing the liveness of its keys, which is why it doesn’t allow enumeration; if a

WeakMap

exposed any method to obtain a list of its keys, the list would depend on the state of garbage collection, introducing non-determinism. If you want to have a list of keys, you should use a

Map

rather than a

WeakMap

.

You can learn more about

WeakMap

in the WeakMap object section of the Keyed collections guide.

JavaScript Array Map
JavaScript Array Map

See also

  • Polyfill of

    WeakMap

    in

    core-js
  • Keyed collections
  • Hiding Implementation Details with ECMAScript 6 WeakMaps by Nick Fitzgerald (2014)

  • Map

  • Set

  • WeakSet

As we know from the chapter Garbage collection, JavaScript engine keeps a value in memory while it is “reachable” and can potentially be used.

For instance:


let john = { name: "John" }; // the object can be accessed, john is the reference to it // overwrite the reference john = null; // the object will be removed from memory

Usually, properties of an object or elements of an array or another data structure are considered reachable and kept in memory while that data structure is in memory.

For instance, if we put an object into an array, then while the array is alive, the object will be alive as well, even if there are no other references to it.

Like this:


let john = { name: "John" }; let array = [ john ]; john = null; // overwrite the reference // the object previously referenced by john is stored inside the array // therefore it won't be garbage-collected // we can get it as array[0]

Similar to that, if we use an object as the key in a regular

Map

, then while the

Map

exists, that object exists as well. It occupies memory and may not be garbage collected.

For instance:


let john = { name: "John" }; let map = new Map(); map.set(john, "..."); john = null; // overwrite the reference // john is stored inside the map, // we can get it by using map.keys()


WeakMap

is fundamentally different in this aspect. It doesn’t prevent garbage-collection of key objects.

Let’s see what it means on examples.

WeakSet


WeakSet

behaves similarly:

  • It is analogous to

    Set

    , but we may only add objects to

    WeakSet

    (not primitives).
  • An object exists in the set while it is reachable from somewhere else.
  • Like

    Set

    , it supports

    add

    ,

    has

    and

    delete

    , but not

    size

    ,

    keys()

    and no iterations.

Being “weak”, it also serves as additional storage. But not for arbitrary data, rather for “yes/no” facts. A membership in

WeakSet

may mean something about the object.

For instance, we can add users to

WeakSet

to keep track of those who visited our site:


let visitedSet = new WeakSet(); let john = { name: "John" }; let pete = { name: "Pete" }; let mary = { name: "Mary" }; visitedSet.add(john); // John visited us visitedSet.add(pete); // Then Pete visitedSet.add(john); // John again // visitedSet has 2 users now // check if John visited? alert(visitedSet.has(john)); // true // check if Mary visited? alert(visitedSet.has(mary)); // false john = null; // visitedSet will be cleaned automatically

The most notable limitation of

WeakMap

and

WeakSet

is the absence of iterations, and the inability to get all current content. That may appear inconvenient, but does not prevent

WeakMap/WeakSet

from doing their main job – be an “additional” storage of data for objects which are stored/managed at another place.

map Array Method | JavaScript Tutorial
map Array Method | JavaScript Tutorial

Use case: additional data

The main area of application for

WeakMap

is an additional data storage.

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.

We put the data to a

WeakMap

, using the object as the key, and when the object is garbage collected, that data will automatically disappear as well.


weakMap.set(john, "secret documents"); // if john dies, secret documents will be destroyed automatically

Let’s look at an example.

For instance, we have code that keeps a visit count for users. The information is stored in a map: a user object is the key and the visit count is the value. When a user leaves (its object gets garbage collected), we don’t want to store their visit count anymore.

Here’s an example of a counting function with

Map

:


// 📁 visitsCount.js let visitsCountMap = new Map(); // map: user => visits count // increase the visits count function countUser(user) { let count = visitsCountMap.get(user) || 0; visitsCountMap.set(user, count + 1); }

And here’s another part of the code, maybe another file using it:


// 📁 main.js let john = { name: "John" }; countUser(john); // count his visits // later john leaves us john = null;

Now,

john

object should be garbage collected, but remains in memory, as it’s a key in

visitsCountMap

.

We need to clean

visitsCountMap

when we remove users, otherwise it will grow in memory indefinitely. Such cleaning can become a tedious task in complex architectures.

We can avoid it by switching to

WeakMap

instead:


// 📁 visitsCount.js let visitsCountMap = new WeakMap(); // weakmap: user => visits count // increase the visits count function countUser(user) { let count = visitsCountMap.get(user) || 0; visitsCountMap.set(user, count + 1); }

Now we don’t have to clean

visitsCountMap

. After

john

object becomes unreachable, by all means except as a key of

WeakMap

, it gets removed from memory, along with the information by that key from

WeakMap

.

WeakMap

The first difference between

Map

and

WeakMap

is that keys must be objects, not primitive values:

Now, if we use an object as the key in it, and there are no other references to that object – it will be removed from memory (and from the map) automatically.


let john = { name: "John" }; let weakMap = new WeakMap(); weakMap.set(john, "..."); john = null; // overwrite the reference // john is removed from memory!

Compare it with the regular

Map

example above. Now if

john

only exists as the key of

WeakMap

– it will be automatically deleted from the map (and memory).


WeakMap

does not support iteration and methods

keys()

,

values()

,

entries()

, so there’s no way to get all keys or values from it.


WeakMap

has only the following methods:

Why such a limitation? That’s for technical reasons. If an object has lost all other references (like

john

in the code above), then it is to be garbage-collected automatically. But technically it’s not exactly specified when the cleanup happens.

The JavaScript engine decides that. It may choose to perform the memory cleanup immediately or to wait and do the cleaning later when more deletions happen. So, technically, the current element count of a

WeakMap

is not known. The engine may have cleaned it up or not, or did it partially. For that reason, methods that access all keys/values are not supported.

Now, where do we need such a data structure?

Array Iteration: 8 Methods - map, filter, reduce, some, every, find, findIndex, forEach
Array Iteration: 8 Methods – map, filter, reduce, some, every, find, findIndex, forEach

Iterate Through a Map

You can iterate through the Map elements using the for…of loop or forEach() method. The elements are accessed in the insertion order. For example,


let map1 = new Map(); map1.set('name', 'Jack'); map1.set('age', '27'); // looping through Map for (let [key, value] of map1) { console.log(key + '- ' + value); }

Output

name- Jack age- 27

You could also get the same results as the above program using the

forEach()

method. For example,


// using forEach method() let map1 = new Map(); map1.set('name', 'Jack'); map1.set('age', '27'); // looping through Map map1.forEach(function(value, key) { console.log(key + '- ' + value) })

Instance methods


WeakMap.prototype.delete()

Removes any value associated to the


key

.

WeakMap.prototype.has(key)

will return

false

afterwards.


WeakMap.prototype.get()

Returns the value associated to the


key

, or

undefined

if there is none.


WeakMap.prototype.has()

Returns a Boolean asserting whether a value has been associated to the


key

in the

WeakMap

object or not.


WeakMap.prototype.set()

Sets the


value

for the

key

in the

WeakMap

object. Returns the

WeakMap

object.

Weak References, Reachability, WeakSets, and WeakMaps
Weak References, Reachability, WeakSets, and WeakMaps

WeakMaps Are Not iterable

Unlike Maps, WeakMaps are not iterable. For example,


const weakMap = new WeakMap(); console.log(weakMap); // WeakMap {} let obj = {}; // adding object (element) to WeakMap weakMap.set(obj, 'hello'); // looping through WeakMap for (let i of weakMap) { console.log(i); // TypeError }

JavaScript

Map

and

WeakMap

were introduced in ES6. Some browsers may not support their use. To learn more, visit JavaScript Map support and JavaScript WeakMap support.

As we know from the chapter Garbage collection, JavaScript engine keeps a value in memory while it is “reachable” and can potentially be used.

For instance:


let john = { name: "John" }; // the object can be accessed, john is the reference to it // overwrite the reference john = null; // the object will be removed from memory

Usually, properties of an object or elements of an array or another data structure are considered reachable and kept in memory while that data structure is in memory.

For instance, if we put an object into an array, then while the array is alive, the object will be alive as well, even if there are no other references to it.

Like this:


let john = { name: "John" }; let array = [ john ]; john = null; // overwrite the reference // the object previously referenced by john is stored inside the array // therefore it won't be garbage-collected // we can get it as array[0]

Similar to that, if we use an object as the key in a regular

Map

, then while the

Map

exists, that object exists as well. It occupies memory and may not be garbage collected.

For instance:


let john = { name: "John" }; let map = new Map(); map.set(john, "..."); john = null; // overwrite the reference // john is stored inside the map, // we can get it by using map.keys()


WeakMap

is fundamentally different in this aspect. It doesn’t prevent garbage-collection of key objects.

Let’s see what it means on examples.

Supported Browsers:

  • Chrome
  • Edge
  • Firefox
  • Opera
  • Safari
  • Internet Explorer

We have a complete list of Javascript Map methods, to check them please go through the Javascript Map Reference article.

Whether you’re preparing for your first job interview or aiming to upskill in this ever-evolving tech landscape, GeeksforGeeks Courses are your key to success. We provide top-quality content at affordable prices, all geared towards accelerating your growth in a time-bound manner. Join the millions we’ve already empowered, and we’re here to do the same for you. Don’t miss out – check it out now!

Looking for a place to share your ideas, learn, and connect? Our Community portal is just the spot! Come join us and see what all the buzz is about!

Last Updated :
16 Jan, 2024

Like Article

Save Article

Share your thoughts in the comments

Please Login to comment…

Looking this and this MDN pages it seems like the only difference between Maps and WeakMaps is a missing “size” property for WeakMaps. But is this true? What’s the difference between them?

  • The effect is on the GC. WeakMaps can have their keys collected. Mar 24, 2013 at 21:35
  • @JanDvorak there’s no example pointed on MDN about it. Like aWeakMap.get(key); // say, 2 …(GC action)… aWeakMap.get(key); // say, undefined Mar 25, 2013 at 4:34
  • 1Your example is impossible.

    key

    cannot be collected, because it’s referenced by you. Mar 25, 2013 at 4:43
  • 1The design decision is that GC actions are invisible in Javascript. You can’t observe GC doing its thing. Mar 25, 2013 at 5:58
  • 1See this related answer for more information about this problem. Aug 16, 2015 at 17:22
JavaScript Map and Set Explained
JavaScript Map and Set Explained

JavaScript Map vs Object

Map Object
Maps can contain objects and other data types as keys. Objects can only contain strings and symbols as keys.
Maps can be directly iterated and their value can be accessed. Objects can be iterated by accessing its keys.
The number of elements of a Map can be determined by The number of elements of an object needs to be determined manually.
Map performs better for programs that require the addition or removal of elements frequently. Object does not perform well if the program requires the addition or removal of elements frequently.

Keywords searched by users: map and weakmap in javascript

Map Vs Weakmap In Javascript - When To Use Map Vs Weakmap? - Youtube
Map Vs Weakmap In Javascript – When To Use Map Vs Weakmap? – Youtube
Minko Gechev On X:
Minko Gechev On X: “Javascript Tip: Using Weakmaps Could Be Very Powerful Especially In Memory Sensitive Apps. Keys Are Weakly Referenced, Which Does Not Prevent Garbage Collection! This Way You Can Stop
When To Use Map Vs Weakmap In Javascript — Eightify
When To Use Map Vs Weakmap In Javascript — Eightify
Javascript Sự Khác Biệt Map Và Weakmap. What Make A Different? | Topdev
Javascript Sự Khác Biệt Map Và Weakmap. What Make A Different? | Topdev
Map, Set, Weakmap & Weakset In Javascript - Real Use Case - Youtube
Map, Set, Weakmap & Weakset In Javascript – Real Use Case – Youtube
44. Es6 Weak Map Object. Difference Between Weakmap And Map Object In  Javascript. Es6 | Es2015 - Youtube
44. Es6 Weak Map Object. Difference Between Weakmap And Map Object In Javascript. Es6 | Es2015 – Youtube
Javascript: Map, Set, Weakmap, Weakset - Examples & Features — Eightify
Javascript: Map, Set, Weakmap, Weakset – Examples & Features — Eightify
Javascript Sự Khác Biệt Map Và Weakmap. What Make A Different? | Topdev
Javascript Sự Khác Biệt Map Và Weakmap. What Make A Different? | Topdev
Map Vs Weakmap In Javascript - Youtube
Map Vs Weakmap In Javascript – Youtube

See more here: kientrucannam.vn

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *