Home >Web Front-end >JS Tutorial >ES6 Collections: Using Map, Set, WeakMap, WeakSet

ES6 Collections: Using Map, Set, WeakMap, WeakSet

Joseph Gordon-Levitt
Joseph Gordon-LevittOriginal
2025-02-15 12:37:11825browse

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.

Key Points

  • ES6 introduces four new data structures: Map, Set, WeakSet and WeakMap. These collections allow for more expressive and powerful JavaScript programming.
  • Map and Set in ES6 are collections of key-value pairs of any type. They are optimized for quick retrieval and provide methods to add, delete, and loop through values. However, they hold strong references to objects, which can be expensive if the objects are large and no longer needed.
  • ES6 also introduces WeakMap and WeakSet, which are similar to Map and Set but hold weak references to objects. This means that when these objects are no longer needed, they can be garbage collected, which is very beneficial for memory management.
  • While the new ES6 collection provides greater flexibility, in many cases, JavaScript objects can still be used as collections. When deciding whether to use objects or keyed collections, developers should consider factors such as the need for dynamic key lookups, interchangeability of values, and the frequency of adding or deleting key-value pairs.

Looking for JavaScript HashMap

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.

Disadvantage#1: The key in ES5 must be a string

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.

Disadvantage#2: Objects are not inherently iterable

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.

Disadvantage #3: Challenges of built-in method conflicts

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.

Using ES6 Map Collection

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:

Create a map and use common 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

Using Set

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

Weak collections, memory and garbage collection

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

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>

User Cases

WeakMap has several popular use cases. They can be used to keep the private data of objects private, or to track DOM nodes/objects.

Private Data Use Cases

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.

DOM node use case

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

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 all things? Records and ES6 collection

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:

    Do the
  • keys usually not known until they are run? Do you need to find them dynamically?
  • All values ​​have the same type and can be used interchangeably?
  • Do you need a key that is not a string?
  • Are key-value pairs added or deleted frequently?
  • Do you have any number (easy to change) of key-value pairs?
  • Is the collection iterated?

New ES6 collections produce easier JavaScript

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.

FAQs about ES6 collections (FAQ): Map, Set, WeakMap, WeakSet

What is the main difference between Map and WeakMap in JavaScript ES6?

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.

How to iterate over WeakMap or WeakSet in JavaScript ES6?

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.

Can I use the original data type as key in WeakMap or WeakSet?

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.

Why should I use WeakMap or WeakSet instead of Map or Set?

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.

What happens when a key in a WeakMap or WeakSet is garbage collected?

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.

Can I use WeakMap or WeakSet to store temporary data?

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.

How to check if WeakMap or WeakSet contains a certain key or value?

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.

Can I delete an entry from a WeakMap or WeakSet?

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.

Can I clear all entries in WeakMap or WeakSet?

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.

Can I get the size of a WeakMap or WeakSet?

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!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn