本文翻译自:What are the actual uses of ES6 WeakMap?

What are the actual uses of the WeakMap data structure introduced in ECMAScript 6? ECMAScript 6中引入的WeakMap数据结构的实际用途是什么?

Since a key of a weak map creates a strong reference to its corresponding value, ensuring that a value which has been inserted into a weak map will never disappear as long as its key is still alive, it can't be used for memo tables, caches or anything else that you would normally use weak references, maps with weak values, etc. for. 由于弱映射的键会对其对应的值建立强引用,因此确保只要弱键仍处于活动状态,插入到弱映射中的值就不会消失,因此不能将其用于备忘表,缓存或其他通常使用弱引用,弱值映射等的内容。

It seems to me that this: 在我看来,这是:

weakmap.set(key, value);

...is just a roundabout way of saying this: ...只是一种回旋的说法:

key.value = value;

What concrete use cases am I missing? 我缺少哪些具体用例?


#1楼

参考:https://stackoom.com/question/1zPio/ES-WeakMap的实际用途是什么


#2楼

This answer seems to be biased and unusable in a real world scenario. 在现实世界中,这个答案似乎是有偏见且无法使用的。 Please read it as is, and don't consider it as an actual option for anything else than experimentation 请按原样阅读,不要将其视为除实验以外的其他选择

A use case could be to use it as a dictionary for listeners, I have a coworker who did that. 一个用例可能是将其用作侦听器的字典,我有一个这样做的同事。 It is very helpful because any listener is directly targetted with this way of doing things. 这非常有用,因为任何听众都可以通过这种方式直接成为目标。 Goodbye listener.on . 再见listener.on

But from a more abstract point of view, WeakMap is especially powerful to dematerialize access to basically anything, you don't need a namespace to isolate its members since it is already implied by the nature of this structure. 但是从更抽象的角度来看, WeakMap尤其强大,可以取消对基本上所有内容的访问,您不需要名称空间来隔离其成员,因为该结构的性质已经暗示了该名称空间。 I'm pretty sure you could do some major memory improvements by replacing awkwards redundant object keys (even though deconstructing does the work for you). 我很确定您可以通过替换笨拙的冗余对象键来进行一些重大的内存改进(即使解构可以为您工作)。


Before reading what is next 在阅读下一步之前

I do now realize my emphasize is not exactly the best way to tackle the problem and as Benjamin Gruenbaum pointed out (check out his answer, if it's not already above mine :p), this problem could not have been solved with a regular Map , since it would have leaked, thus the main strength of WeakMap is that it does not interfere with garbage collection given that they do not keep a reference. 我现在确实意识到我的强调并不完全是解决问题的最佳方法,并且正如本杰明·格伦鲍姆 ( Benjamin Gruenbaum)所指出的(请查看他的回答,如果它不在我的:p之上),则无法使用常规Map来解决此问题,因为它会泄漏,所以WeakMap的主要优点在于,只要不保留引用,它就不会干扰垃圾回收。


Here is the actual code of my coworker (thanks to him for sharing) 这是我同事的实际代码(感谢他的分享)

Full source here , it's about listeners management I talked about above (you can also take a look at the specs ) 这里的完整源代码是关于我在上面讨论的监听器管理的(您也可以查看规范 )

var listenableMap = new WeakMap();export function getListenable (object) {if (!listenableMap.has(object)) {listenableMap.set(object, {});}return listenableMap.get(object);
}export function getListeners (object, identifier) {var listenable = getListenable(object);listenable[identifier] = listenable[identifier] || [];return listenable[identifier];
}export function on (object, identifier, listener) {var listeners = getListeners(object, identifier);listeners.push(listener);
}export function removeListener (object, identifier, listener) {var listeners = getListeners(object, identifier);var index = listeners.indexOf(listener);if(index !== -1) {listeners.splice(index, 1);}
}export function emit (object, identifier, ...args) {var listeners = getListeners(object, identifier);for (var listener of listeners) {listener.apply(object, args);}
}

#3楼

Fundamentally 从根本上

WeakMaps provide a way to extend objects from the outside without interfering with garbage collection. WeakMaps提供了一种从外部扩展对象而不干扰垃圾回收的方法。 Whenever you want to extend an object but can't because it is sealed - or from an external source - a WeakMap can be applied. 每当您想扩展对象但由于密封而不能扩展对象时(或者从外部源扩展)时,都可以应用WeakMap。

A WeakMap is a map (dictionary) where the keys are weak - that is, if all references to the key are lost and there are no more references to the value - the value can be garbage collected. WeakMap是键弱的地图(词典),也就是说,如果丢失了对键的所有引用,并且不再有对该值的引用,则可以对该进行垃圾回收。 Let's show this first through examples, then explain it a bit and finally finish with real use. 让我们首先通过示例展示它,然后进行一些解释,最后完成实际使用。

Let's say I'm using an API that gives me a certain object: 假设我使用的API给了我一个特定的对象:

var obj = getObjectFromLibrary();

Now, I have a method that uses the object: 现在,我有一个使用该对象的方法:

function useObj(obj){doSomethingWith(obj);
}

I want to keep track of how many times the method was called with a certain object and report if it happens more than N times. 我想跟踪用某个对象调用该方法的次数,并报告该方法是否发生了N次以上。 Naively one would think to use a Map: 天真的会想到使用Map:

var map = new Map(); // maps can have object keys
function useObj(obj){doSomethingWith(obj);var called = map.get(obj) || 0;called++; // called one more timeif(called > 10) report(); // Report called more than 10 timesmap.set(obj, called);
}

This works, but it has a memory leak - we now keep track of every single library object passed to the function which keeps the library objects from ever being garbage collected. 这可行,但是会发生内存泄漏-我们现在跟踪传递给该函数的每个库对象,从而避免垃圾回收。 Instead - we can use a WeakMap : 相反,我们可以使用WeakMap

var map = new WeakMap(); // create a weak map
function useObj(obj){doSomethingWith(obj);var called = map.get(obj) || 0;called++; // called one more timeif(called > 10) report(); // Report called more than 10 timesmap.set(obj, called);
}

And the memory leak is gone. 并且内存泄漏消失了。

Use cases 用例

Some use cases that would otherwise cause a memory leak and are enabled by WeakMap s include: 某些会导致内存泄漏并由WeakMap启用的用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. 私有符号提案中出现了一种更临时的方法,但是距离现在还有很长时间。
  • Keeping data about library objects without changing them or incurring overhead. 保留有关库对象的数据,而无需更改它们或引起开销。
  • Keeping data about a small set of objects where many objects of the type exist to not incur problems with hidden classes JS engines use for objects of the same type. 保留有关少量对象的数据(其中存在许多类型的对象)不会引起JS引擎用于相同类型的对象的隐藏类问题。
  • Keeping data about host objects like DOM nodes in the browser. 在浏览器中保留有关主机对象(如DOM节点)的数据。
  • Adding a capability to an object from the outside (like the event emitter example in the other answer). 从外部向对象添加功能(如另一个答案中的事件发射器示例)。

Let's look at a real use 让我们看一下真正的用途

It can be used to extend an object from the outside. 它可以用于从外部扩展对象。 Let's give a practical (adapted, sort of real - to make a point) example from the real world of Node.js. 让我们从Node.js的真实世界中给出一个实用的(经过改编的,真实的)实例。

Let's say you're Node.js and you have Promise objects - now you want to keep track of all the currently rejected promises - however, you do not want to keep them from being garbage collected in case no references exist to them. 比方说,你的Node.js,你有Promise对象-现在你要保留所有当前被拒绝承诺的轨道-但是,你不想让他们被的情况下,垃圾收集没有引用存在于他们。

Now, you don't want to add properties to native objects for obvious reasons - so you're stuck. 现在,你不想将属性添加到本地对象的原因很明显-这样你就完蛋了。 If you keep references to the promises you're causing a memory leak since no garbage collection can happen. 如果保留对Promise的引用,则将导致内存泄漏,因为不会发生垃圾回收。 If you don't keep references then you can't save additional information about individual promises. 如果您不保留引用,那么您将无法保存有关单个承诺的其他信息。 Any scheme that involves saving the ID of a promise inherently means you need a reference to it. 任何涉及保存承诺ID的方案本质上都意味着您需要对其进行引用。

Enter WeakMaps 输入弱地图

WeakMaps mean that the keys are weak. WeakMaps表示键很弱。 There are no ways to enumerate a weak map or to get all its values. 无法枚举弱映射或获取其所有值。 In a weak map, you can store the data based on a key and when the key gets garbage collected so do the values. 在弱映射中,您可以基于密钥存储数据,并且在密钥被垃圾回收时也存储值。

This means that given a promise you can store state about it - and that object can still be garbage collected. 这意味着只要有一个承诺,您就可以存储有关它的状态-而且该对象仍可以被垃圾回收。 Later on, if you get a reference to an object you can check if you have any state relating to it and report it. 稍后,如果获得对对象的引用,则可以检查是否具有与该对象相关的任何状态并报告该状态。

This was used to implement unhandled rejection hooks by Petka Antonov as this : Petka Antonov用来实现未处理的拒绝挂钩 ,如下所示 :

process.on('unhandledRejection', function(reason, p) {console.log("Unhandled Rejection at: Promise ", p, " reason: ", reason);// application specific logging, throwing an error, or other logic here
});

We keep information about promises in a map and can know when a rejected promise was handled. 我们将有关诺言的信息保存在地图中,并且可以知道何时处理了被拒绝的诺言。


#4楼

WeakMap works well for encapsulation and information hiding WeakMap非常适合封装和信息隐藏

WeakMap is only available for ES6 and above. WeakMap仅适用于ES6及更高版本。 A WeakMap is a collection of key and value pairs where the key must be an object. WeakMap是键和值对的集合,其中键必须是一个对象。 In the following example, we build a WeakMap with two items: 在以下示例中,我们构建了一个包含两个项目的WeakMap

var map = new WeakMap();
var pavloHero = {first: "Pavlo", last: "Hero"};
var gabrielFranco = {first: "Gabriel", last: "Franco"};
map.set(pavloHero, "This is Hero");
map.set(gabrielFranco, "This is Franco");
console.log(map.get(pavloHero));//This is Hero

We used the set() method to define an association between an object and another item (a string in our case). 我们使用set()方法定义一个对象与另一个项目(在我们的例子中为字符串)之间的关联。 We used the get() method to retrieve the item associated with an object. 我们使用了get()方法来检索与对象关联的项目。 The interesting aspect of the WeakMap s is the fact that it holds a weak reference to the key inside the map. WeakMap有趣的方面是它对地图内部的键的引用很弱。 A weak reference means that if the object is destroyed, the garbage collector will remove the entire entry from the WeakMap , thus freeing up memory. 弱引用意味着如果对象被破坏,则垃圾收集器将从WeakMap删除整个条目,从而释放内存。

var TheatreSeats = (function() {var priv = new WeakMap();var _ = function(instance) {return priv.get(instance);};return (function() {function TheatreSeatsConstructor() {var privateMembers = {seats: []};priv.set(this, privateMembers);this.maxSize = 10;}TheatreSeatsConstructor.prototype.placePerson = function(person) {_(this).seats.push(person);};TheatreSeatsConstructor.prototype.countOccupiedSeats = function() {return _(this).seats.length;};TheatreSeatsConstructor.prototype.isSoldOut = function() {return _(this).seats.length >= this.maxSize;};TheatreSeatsConstructor.prototype.countFreeSeats = function() {return this.maxSize - _(this).seats.length;};return TheatreSeatsConstructor;}());
})()

#5楼

ES6 WeakMap的实际用途是什么?相关推荐

  1. es6 WeakMap

    WeakMap 含义 WeakMap结构与Map结构类似,也是用于生成键值对的集合. // WeakMap 可以使用 set 方法添加成员 const wm1 = new WeakMap(); con ...

  2. ES6结构赋值的用途

    (1)交换变量的值 let x = 1; let y = 2;[x, y] = [y, x]; 上面代码交换变量x和y的值,这样的写法不仅简洁,而且易读,语义非常清晰 (2)从函数返回多个值 函数只能 ...

  3. ES6新特性(中)——ES6的集合(set集合、map集合等)

    这里写目录标题 ES6的集合 一.Set集合 1.操作方法 2.遍历方法: 二.WeakSet集合 1.概念理解 2.方法: 3.WeakSet 的应用场景/好处 三.Map集合 1.概念理解 2.属 ...

  4. 野生前端的数据结构基础练习(6)——集合

    [摘要] 集合Set是一种不包含不同元素的数据结构,主要特性包括无序性和单一性,即集合中的成员是无序的,同时也是不重复的. 网上的相关教程非常多,基础知识自行搜索即可. 习题主要选自Orelly出版的 ...

  5. JavaScript权威指南7(四) 第十一章 JavaScript 标准库

    Set和Map类 用于表示一组值以及从一组值到另一组值的映射. set 是值得集合,就像数组.但不同于数组,set 没有被排序或索引,并且它们不允许重复:值要么是集合的成员要么不是集合的成员,不能知道 ...

  6. 《JavaScript权威指南第7版》第11章 JavaScript标准库

    第11章 JavaScript标准库 11.1 Set和Map 11.1.1 Set类 11.1.2 Map类 11.1.3 WeakMap和WeakSet 11.2 类型数组和二进制数据 11.2. ...

  7. JavaScript权威指南 第11章JavaScript标准库

    JavaScript权威指南 第11章JavaScript标准库 第11章 JavaScript标准库 11.1 集合与映射 11.1.1 Set类 11.1.2 Map类 11.1.3 WeakMa ...

  8. web 前端学习线路图

    web 前端学习线路图 一.HTML 教程 HTML教程 HTML简介 HTML编辑器 HTML基础 HTML元素 HTML属性 HTML标题 HTML段落 HTML样式 HTML格式化 HTML引用 ...

  9. 《学习JavaScript数据结构与算法》 第四章笔记 栈

    文章目录 前言 一.栈? 二.构建两种栈的大致步骤 三.创建基于数组的栈 创建class Stack 定义用于操作栈的方法 使用栈 四.创建基于对象的栈 创建class Stack 定义用于操作栈的方 ...

最新文章

  1. 因女朋友的一个建议,这位程序员创立仅 551 天公司就被 10 亿美元收购了
  2. 还有人记得【日之韵】吗?——提供下载
  3. dSploitzANTI渗透教程之HTTP服务重定向地址
  4. C 语言获取系统时间
  5. 链表相交以及找循环链表入口
  6. ASP.NET MVC 上传文件
  7. 【CV】通俗易懂的目标检测 | RCNN, SPPNet, Fast, Faster
  8. 在mybatis中调oracle dblink存储过程
  9. C函数形参列表与汇编寄存器的对应关系
  10. 树状数组相关应用之区间包含问题
  11. Awesome Go
  12. select支持手动输入
  13. Filter_Listener:过滤器和监听器
  14. 好友管理系统 Python
  15. Python使用超级鹰识别验证码
  16. C#|图像快速傅立叶变换与反变换
  17. Linux下复制粘贴快捷键
  18. 用以太坊区块链和jwt token保证Asp.Net Core的API交互安全(上)
  19. iPhone十年,移动用户体验领域已经到达成熟阶段
  20. springboot学习

热门文章

  1. 《包青天》中的《鸳鸯蝴蝶梦》单元,剧中有一个很漂亮的女子叫“离垢”
  2. Android必知必会-Android Studio下配置和使用Lambda
  3. Android启动失败
  4. 算法---------数组-----------寻找峰值
  5. 【剑指offer-Java版】33把数组排成最小的数
  6. 读取excel日期 c++_实例9:用Python自动生成Excel档每日出货清单
  7. node--非阻塞式I/O,单线程,异步,事件驱动
  8. 使用PHPStorm 配置自定义的Apache与PHP环境
  9. a标签跳页传参,以及截取URL参数
  10. ThinkPHP5 清除runtime缓存文件