ES6 WeakMap 的实际用途是什么? [英] What are the actual uses of ES6 WeakMap?

查看:16
本文介绍了ES6 WeakMap 的实际用途是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

ECMAScript 6 中引入的 WeakMap 数据结构的实际用途是什么?

What are the actual uses of the WeakMap data structure introduced in ECMAScript 6?

由于弱映射的键创建了对其对应值的强引用,确保插入弱映射的值永远不会消失,只要其键仍然存在,它不能用于备忘录表、缓存或其他任何您通常会使用弱引用、具有弱值的映射等的内容.

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.

在我看来:

weakmap.set(key, value);

...只是一种迂回的说法:

...is just a roundabout way of saying this:

key.value = value;

我缺少哪些具体用例?

推荐答案

从根本上

WeakMaps 提供了一种从外部扩展对象而不干扰垃圾收集的方法.每当你想扩展一个对象但不能因为它是密封的 - 或者来自外部源 - WeakMap可以申请.

Fundamentally

WeakMaps provide a way to extend objects from the outside without interfering with garbage collection. 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 是一个映射(字典),其中 是弱的——也就是说,如果对 的所有引用都丢失了,并且不再有对 的引用value - value 可以被垃圾回收.我们先通过例子来说明,然后稍微解释一下,最后以实际使用结束.

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. Let's show this first through examples, then explain it a bit and finally finish with real use.

假设我使用的 API 为我提供了某个对象:

Let's say I'm using an API that gives me a certain object:

var obj = getObjectFromLibrary();

现在,我有一个使用对象的方法:

Now, I have a method that uses the object:

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

我想跟踪某个对象调用该方法的次数,并报告它发生的次数是否超过 N 次.天真的人会想到使用地图:

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. Naively one would think to use a 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 time
    if(called > 10) report(); // Report called more than 10 times
    map.set(obj, called);
}

这有效,但它有内存泄漏 - 我们现在跟踪传递给函数的每个库对象,以防止库对象被垃圾收集.相反 - 我们可以使用 WeakMap:

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:

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

内存泄漏消失了.

一些会导致内存泄漏并由 WeakMap 启用的用例包括:

Some use cases that would otherwise cause a memory leak and are enabled by WeakMaps include:

  • 保留有关特定对象的私有数据,并且仅将访问权限授予具有地图引用的人员.随着私有符号提案的出现,一种更临时的方法即将出现,但那是很久以后的事了.
  • 保留有关库对象的数据而不更改它们或产生开销.
  • 保留关于一小组对象的数据,其中存在许多该类型的对象,以免 JS 引擎用于相同类型的对象的隐藏类出现问题.
  • 在浏览器中保存有关主机对象(如 DOM 节点)的数据.
  • 从外部向对象添加功能(如另一个答案中的事件发射器示例).

它可用于从外部扩展对象.让我们从 Node.js 的真实世界中给出一个实际的(改编的,有点真实 - 以说明问题)示例.

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 并且你有 Promise 对象——现在你想跟踪所有当前被拒绝的承诺——但是,你想要防止它们被垃圾收集,以防不存在对它们的引用.

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.

现在,由于显而易见的原因,您不想想要向本机对象添加属性 - 所以您被卡住了.如果您保留对承诺的引用,则会导致内存泄漏,因为不会发生垃圾收集.如果您不保留引用,则无法保存有关个人承诺的其他信息.任何涉及保存承诺 ID 的方案本质上都意味着您需要对它的引用.

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. 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.

WeakMaps 意味着 很弱.没有办法枚举弱映射或获取其所有值.在弱映射中,您可以根据键存储数据,当键被垃圾回收时,值也会被回收.

WeakMaps mean that the keys are weak. 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.

这被 Petka Antonov 用作 未处理的拒绝钩子href="https://iojs.org/api/process.html#process_event_unhandledrejection" rel="noreferrer">这个:

This was used to implement unhandled rejection hooks by Petka Antonov as this:

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.

这篇关于ES6 WeakMap 的实际用途是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆