简体   繁体   English

ES6 Set、WeakSet、Map 和 WeakMap

[英]ES6 Set, WeakSet, Map and WeakMap

There is already some questions about map and weak maps, like this: What's the difference between ES6 Map and WeakMap?已经有一些关于map 和weakmap的问题,比如: ES6 Map和WeakMap有什么区别? but I would like to ask in which situation should I favor the use of these data structures?但是我想问一下在什么情况下我应该更喜欢使用这些数据结构? Or what should I take in consideration when I favor one over the others?或者当我偏爱一个而不是其他时,我应该考虑什么?

Examples of the data structures from: https://github.com/lukehoban/es6features数据结构示例来自: https : //github.com/lukehoban/es6features

// Sets
var s = new Set();
s.add("hello").add("goodbye").add("hello");
s.size === 2;
s.has("hello") === true;

// Maps
var m = new Map();
m.set("hello", 42);
m.set(s, 34);
m.get(s) == 34;

// Weak Maps
var wm = new WeakMap();
wm.set(s, { extra: 42 });
wm.size === undefined

// Weak Sets
var ws = new WeakSet();
ws.add({ data: 42 });
// Because the added object has no other references, it will not be held in the set

Bonus.奖金。 Which of the above data structures will produce the same/similar result of doing: let hash = object.create(null); hash[index] = something;上述哪个数据结构会产生相同/相似的结果: let hash = object.create(null); hash[index] = something; let hash = object.create(null); hash[index] = something;

This is covered in §23.3 of the specification:这在规范的§23.3中有所涉及:

If an object that is being used as the key of a WeakMap key/value pair is only reachable by following a chain of references that start within that WeakMap , then that key/value pair is inaccessible and is automatically removed from the WeakMap .如果被用作WeakMap键/值对的键的对象只能通过遵循从该WeakMap中开始的一系列引用来WeakMap ,那么该键/值对是不可访问的,并且会自动从WeakMap删除。

So the entries in a weak map, if their keys aren't referenced by anything else, will be reclaimed by garbage collection at some point.所以弱映射中的条目,如果它们的键没有被其他任何东西引用,将在某个时候被垃圾收集回收。

In contrast, a Map holds a strong reference to its keys, preventing them from being garbage-collected if the map is the only thing referencing them.相比之下, Map持有对其键的引用,如果 Map 是唯一引用它们的东西,则可以防止它们被垃圾收集。

MDN puts it like this : MDN 是这样写的

The key in a WeakMap is held weakly. WeakMap的键被弱持有。 What this means is that, if there are no other strong references to the key, then the entire entry will be removed from the WeakMap by the garbage collector.这意味着,如果没有其他对该键的强引用,则垃圾收集器将从WeakMap删除整个条目。

And WeakSet does the same. WeakSet如此。

...in which situation should I favor the use of this data structures? ...在哪种情况下我应该赞成使用这种数据结构?

Any situation where you don't want the fact you have a map/set using a key to prevent that key from being garbage-collected.在任何情况下,您不希望您拥有使用键的映射/集合来防止该键被垃圾收集。 Here are some examples:这里有些例子:

  1. Having instance-specific information which is truly private to the instance, which looks like this: (Note: This example is from 2015, well before private fields were an option. Here in 2021, I'd use private fields for this.)拥有对实例真正私有的特定于实例的信息,如下所示:(注意:此示例来自 2015 年,早在私有字段成为选项之前。在 2021 年,我将为此使用私有字段。)

     let Thing = (() => { var privateData = new WeakMap(); class Thing { constructor() { privateData[this] = { foo: "some value" }; } doSomething() { console.log(privateData[this].foo); } } return Thing; })();

    There's no way for code outside that scoping function to access the data in privateData .该作用域函数之外的代码无法访问privateData的数据。 That data is keyed by the instance itself.该数据由实例本身键控。 You wouldn't do that without a WeakMap because it would be a memory leak, your Thing instances would never be cleaned up.如果没有WeakMap ,你就不会这样做,因为这会造成内存泄漏,你的Thing实例永远不会被清理。 But WeakMap only holds weak references, and so if your code using a Thing instance is done with it and releases its reference to the instance, the WeakMap doesn't prevent the instance from being garbage-collected;但是WeakMap只保存引用,所以如果你的代码使用Thing实例并释放它对实例的引用, WeakMap不会阻止实例被垃圾收集; instead, the entry keyed by the instance is removed from the map.相反,实例键控的条目会从映射中删除。

  2. Holding information for objects you don't control.保存您无法控制的对象的信息。 Suppose you get an object from some API and you need to remember some additional information about that object.假设您从某个 API 获取一个对象,并且您需要记住有关该对象的一些附加信息。 You could add properties to the object itself (if it's not sealed), but adding properties to objets outside of your control is just asking for trouble.可以将属性添加到对象本身(如果它不是密封的),但添加属性OBJETS你的控制之外被找麻烦 Instead, you can use a WeakMap keyed by the object to store your extra information.相反,您可以使用由对象键控的WeakMap来存储您的额外信息。

  3. One use case for WeakSet is tracking or branding: Suppose that before "using" an object, you need to know whether that object has ever been "used" in the past, but without storing that as a flag on the object (perhaps because if it's a flag on the object, other code can see it [though you could use a private field to prevent that]; or because it's not your object [so private fields wouldn't help]). WeakSet一个用例是跟踪或标记:假设在“使用”一个对象之前,您需要知道该对象过去是否曾被“使用过”,但不将其存储为对象上的标志(可能是因为如果它是对象上的一个标志,其他代码可以看到它[尽管您可以使用私有字段来防止这种情况发生];或者因为它不是您的对象[因此私有字段无济于事])。 For instance, this might be some kind of single-use access token.例如,这可能是某种一次性访问令牌。 A WeakSet is a simple way to do that without forcing the object to stay in memory. WeakSet是一种简单的方法,无需强制对象留在内存中。

Which of the above data structures will produce the same/similar result of doing: let hash = Object.create(null); hash[index] = something;以上哪个数据结构会产生相同/相似的结果: let hash = Object.create(null); hash[index] = something; let hash = Object.create(null); hash[index] = something;

That would be nearest to Map , because the string index (the property name) will be held by a strong reference in the object (it and its associated property will not be reclaimed if nothing else references it).这将最接近Map ,因为字符串index (属性名称)将由对象中的强引用保存(如果没有其他引用,则不会回收它及其关联的属性)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM