Home >Web Front-end >JS Tutorial >ES6 Collections: Using Map, Set, WeakMap, WeakSet
This article explores four new ES6 collections and the benefits they bring.
Most major programming languages have several types of data collections. Python has lists, tuples, and dictionaries. Java has lists, collections, maps, and queues. Ruby has hash and arrays. So far, JavaScript has only arrays. Objects and arrays are JavaScript's right-hand helpers. ES6 introduces four new data structures that will enhance the powerful and expressive capabilities of the language: Map, Set, WeakSet and WeakMap.
HashMap, dictionary, and hash are several ways in which various programming languages store key-value pairs, and these data structures are optimized for fast retrieval.
In ES5, JavaScript objects (just any collection of properties with keys and values) can simulate hashes, but there are several disadvantages to using objects as hashes.
JavaScript object property keys must be strings, which limits their ability to be a collection of key-value pairs of different data types. Of course, you can cast other data types to strings, but this adds extra work.
Objects are not designed as collections, so there is no effective way to determine how many attributes an object has. (For example, Object.keys is slow). When you loop through the properties of an object, you also get its prototype properties. You can add iterable properties to all objects, but not all objects are intended to be used as collections. You can use the for … in loop and hasOwnProperty() method, but this is just a workaround. When you loop through an object's properties, properties are not necessarily retrieved in the order they were inserted.
Objects have built-in methods such as constructor, toString, and valueOf. If one of them is added as a property, it may result in a conflict. You can create a naked object (not inherited from object.prototype) using Object.create(null), but this is still just a workaround.
ES6 contains new collection data types, so no longer needs to use objects and endure their disadvantages.
Map is the first data structure/set we are going to check. A Map is a collection of key-value pairs of any type. It's easy to create new maps, add/remove values, loop through keys/values, and effectively determine their size. Here are the key methods:
<code class="language-javascript">const map = new Map(); // 创建一个新的Map map.set('hobby', 'cycling'); // 设置键值对 const foods = { dinner: 'Curry', lunch: 'Sandwich', breakfast: 'Eggs' }; // 新对象 const normalfoods = {}; // 新对象 map.set(normalfoods, foods); // 设置两个对象作为键值对 for (const [key, value] of map) { console.log(`${key} = ${value}`); // hobby = cycling [object Object] = [object Object] } map.forEach((value, key) => { console.log(`${key} = ${value}`); }, map); // hobby = cycling [object Object] = [object Object] map.clear(); // 清除键值对 console.log(map.size === 0); // True </code>
Run this example on JSBin
Set is an ordered list of values, without duplicates. Set is not indexed like an array, but accessed using keys. Set already exists in Java, Ruby, Python, and many other languages. One difference between ES6 Set and Sets in other languages is that order is important in ES6 (not in many other languages). Here are the key Set methods:
<code class="language-javascript">const planetsOrderFromSun = new Set(); planetsOrderFromSun.add('Mercury'); planetsOrderFromSun.add('Venus').add('Earth').add('Mars'); // 可链式方法 console.log(planetsOrderFromSun.has('Earth')); // True planetsOrderFromSun.delete('Mars'); console.log(planetsOrderFromSun.has('Mars')); // False for (const x of planetsOrderFromSun) { console.log(x); // 输入和输出顺序相同 - Mercury Venus Earth } console.log(planetsOrderFromSun.size); // 3 planetsOrderFromSun.add('Venus'); // 尝试添加重复项 console.log(planetsOrderFromSun.size); // 仍然是3,没有添加重复项 planetsOrderFromSun.clear(); console.log(planetsOrderFromSun.size); // 0 </code>
Run this example on JSBin
JavaScript garbage collection is a form of memory management in which objects that are no longer referenced will be automatically deleted and their resources will be recycled.
Map and Set references to objects are forced to be held and garbage collection is not allowed. This can become expensive if map/set references large objects that are no longer needed (such as DOM elements that have been removed from the DOM).
To solve this problem, ES6 also introduced two new weak sets called WeakMap and WeakSet. These ES6 collections are "weak" because they allow objects that are no longer needed to be cleared from memory.
WeakMap is the third new ES6 collection we introduced. WeakMap is similar to a normal Map, but has fewer methods and there are the above differences in garbage collection.
<code class="language-javascript">const aboutAuthor = new WeakMap(); // 创建新的WeakMap const currentAge = {}; // 键必须是对象 const currentCity = {}; // 键必须是对象 aboutAuthor.set(currentAge, 30); // 设置键值 aboutAuthor.set(currentCity, 'Denver'); // 键值可以是不同数据类型 console.log(aboutAuthor.has(currentCity)); // 测试WeakMap是否包含键 aboutAuthor.delete(currentAge); // 删除键 </code>
WeakMap has several popular use cases. They can be used to keep the private data of objects private, or to track DOM nodes/objects.
The following example comes from JavaScript expert Nicholas C. Zakas:
<code class="language-javascript">var Person = (function() { var privateData = new WeakMap(); function Person(name) { privateData.set(this, { name: name }); } Person.prototype.getName = function() { return privateData.get(this).name; }; return Person; }()); </code>
Using WeakMap here simplifies the process of keeping object data private. Person objects can be referenced, but privateDataWeakMap is not allowed to access if there is no specific Person instance.
The Google Polymer project uses WeakMap in a code snippet called PositionWalker.
PositionWalker tracks the location in the DOM subtree as the current node and the offset within that node.
WeakMap is used to track editing, deleting and changes of DOM nodes:
<code class="language-javascript">const map = new Map(); // 创建一个新的Map map.set('hobby', 'cycling'); // 设置键值对 const foods = { dinner: 'Curry', lunch: 'Sandwich', breakfast: 'Eggs' }; // 新对象 const normalfoods = {}; // 新对象 map.set(normalfoods, foods); // 设置两个对象作为键值对 for (const [key, value] of map) { console.log(`${key} = ${value}`); // hobby = cycling [object Object] = [object Object] } map.forEach((value, key) => { console.log(`${key} = ${value}`); }, map); // hobby = cycling [object Object] = [object Object] map.clear(); // 清除键值对 console.log(map.size === 0); // True </code>
WeakSet is a set of sets whose elements can be garbage collected when objects they reference no longer need. WeakSet does not allow iteration. Their use cases are quite limited (at least for the time being). Most early adopters said WeakSet can be used to tag objects without modifying them. ES6-Features.org has an example of adding and removing elements from WeakSet to keep track of whether the object has been tagged:
<code class="language-javascript">const planetsOrderFromSun = new Set(); planetsOrderFromSun.add('Mercury'); planetsOrderFromSun.add('Venus').add('Earth').add('Mars'); // 可链式方法 console.log(planetsOrderFromSun.has('Earth')); // True planetsOrderFromSun.delete('Mars'); console.log(planetsOrderFromSun.has('Mars')); // False for (const x of planetsOrderFromSun) { console.log(x); // 输入和输出顺序相同 - Mercury Venus Earth } console.log(planetsOrderFromSun.size); // 3 planetsOrderFromSun.add('Venus'); // 尝试添加重复项 console.log(planetsOrderFromSun.size); // 仍然是3,没有添加重复项 planetsOrderFromSun.clear(); console.log(planetsOrderFromSun.size); // 0 </code>
Map and Set are a nice new ES6 collection of key-value pairs. That is, JavaScript objects can still be used as collections in many cases. There is no need to switch to the new ES6 collection unless the situation requires it.
MDN has a good list of questions for determining when to use an object or keyed collection:
JavaScript collections were previously very limited, but this has been corrected with ES6. These new ES6 collections will enhance the power and flexibility of the language and simplify the tasks of JavaScript developers who adopt them.
This article is part of a web development series from Microsoft Technology Evangelist and DevelopIntelligence on practical JavaScript learning, open source projects, and interoperability best practices including the Microsoft Edge browser and the new EdgeHTML rendering engine. DevelopIntelligence offers JavaScript training and React training courses through appendTo, its front-end-focused blog and course website.
We encourage you to test on a variety of browsers and devices including Microsoft Edge, the default browser for Windows 10, and you can use the free tools on dev.microsoftedge.com, including EdgeHTML issue tracking where you can report or search for EdgeHTML issues, such as website rendering or standard compliance issues. Also, visit the Edge blog for the latest information from Microsoft developers and experts.
In JavaScript ES6, both Map and WeakMap are used to store key-value pairs. However, there are some significant differences between them. First, in Map, the key can be of any type, while in WeakMap, the key must be an object. Second, Map has a size property that allows you to check the number of key-value pairs, but WeakMap does not have this property. Finally, Map holds strong references to key objects, meaning that as long as the Map exists, they are not eligible for garbage collection. WeakMap, on the other hand, holds weak references to key objects, meaning that if there are no other references to the object, it can be garbage collected.
Unlike Map and Set, WeakMap and WeakSet have no way to iterate over their elements. This is because they are designed to hold weak references to their keys (WeakMap) or values (WeakSet), which means these can be garbage collected at any time. Therefore, there is no guarantee that the element will still exist when trying to iterate over it. If you need to iterate over the collection, you should use Map or Set instead.
No, you cannot use the original data type as key in WeakMap or WeakSet. The keys in these collections must be objects. This is because WeakMap and WeakSet hold weak references to their keys, which means that if there are no other references to them, the keys can be garbage collected. Primitive data types (such as numbers and strings) are not garbage collected like objects, so they cannot be used as keys in these collections.
WeakMap and WeakSet have some unique features, and in some cases they may be more appropriate than Map or Set. Because they hold weak references to their keys (WeakMap) or values (WeakSet), they can be garbage collected when they are no longer in use. This is useful if you want to associate other data with an object but don't want to prevent the object from garbage collection when it is no longer needed. Furthermore, because WeakMap and WeakSet do not have a way to iterate over their elements, they can provide a certain level of privacy for the data they store.
When keys in WeakMap or WeakSet are garbage collected, the corresponding entries in the collection will be automatically deleted. This is because these sets hold weak references to their keys, which means that when they are no longer in use, the keys can be garbage collected. This feature is useful for managing memory in JavaScript applications because it ensures that data associated with objects that are no longer in use will also be cleared.
Yes, WeakMap and WeakSet are great for storing temporary data. Because they hold weak references to their keys (WeakMap) or values (WeakSet), they can be garbage collected when they are no longer in use. This means that when the keys are garbage collected, the data stored in these sets are also cleared. This is useful for storing what is needed only for a short time, as you don't have to worry about manually cleaning it up.
You can use the has method to check if the WeakMap or WeakSet contains a certain key. This method returns a Boolean value indicating whether the key exists in the collection. However, remember that you cannot use this method to check for a certain value in WeakSet, because the values in this set are inaccessible.
Yes, you can use the delete method to delete the entry from WeakMap. This method deletes the entry associated with the given key and returns a Boolean value indicating whether the key exists in the collection. However, you cannot delete entries from WeakSet because this collection does not have a delete method.
No, you cannot clear all entries in WeakMap or WeakSet. These collections do not have a clear method, which is available in Map and Set. This is because WeakMap and WeakSet are designed to automatically clean up keys when they are garbage collected.
No, you cannot get the size of the WeakMap or WeakSet. These collections do not have a size property, which is available in Map and Set. This is because the size of the WeakMap or WeakSet can be changed at any time due to garbage collection.
The above is the detailed content of ES6 Collections: Using Map, Set, WeakMap, WeakSet. For more information, please follow other related articles on the PHP Chinese website!