javascript ECMAScript 6:WeakSet 有什么用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30556078/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ECMAScript 6: what is WeakSet for?
提问by Robo Robok
The WeakSet is supposed to store elements by weak reference. That is, if an object is not referenced by anything else, it should be cleaned from the WeakSet.
WeakSet 应该通过弱引用存储元素。也就是说,如果一个对象没有被其他任何东西引用,它应该从 WeakSet 中清除。
I have written the following test:
我编写了以下测试:
var weakset = new WeakSet(),
numbers = [1, 2, 3];
weakset.add(numbers);
weakset.add({name: "Charlie"});
console.log(weakset);
numbers = undefined;
console.log(weakset);
Even though my [1, 2, 3]
array is not referenced by anything, it's not being removed from the WeakSet. The console prints:
即使我的[1, 2, 3]
数组没有被任何东西引用,它也不会从 WeakSet 中删除。控制台打印:
WeakSet {[1, 2, 3], Object {name: "Charlie"}}
WeakSet {[1, 2, 3], Object {name: "Charlie"}}
Why is that?
这是为什么?
Plus, I have one more question. What is the point of adding objects to WeakSets directly, like this:
另外,我还有一个问题。直接向 WeakSets 添加对象有什么意义,像这样:
weakset.add({name: "Charlie"});
Are those Traceur's glitches or am I missing something?
是那些 Traceur 的小故障还是我遗漏了什么?
And finally, what is the practical use of WeakSet if we cannot even iterate through it nor get the current size?
最后,如果我们甚至无法遍历它也无法获得当前大小,那么 WeakSet 的实际用途是什么?
回答by Bergi
it's not being removed from the WeakSet. Why is that?
它不会从 WeakSet 中删除。这是为什么?
Most likely because the garbage collector has not yet run. However, you say you are using Traceur, so it just might be that they're not properly supported. I wonder how the console
can show the contents of a WeakSet
anyway.
很可能是因为垃圾收集器尚未运行。但是,您说您正在使用 Traceur,所以可能是因为它们没有得到适当的支持。我想知道无论如何如何console
才能显示 a 的内容WeakSet
。
What is the point of adding objects to WeakSets directly?
直接向 WeakSet 添加对象有什么意义?
There is absolutely no point of adding object literals to WeakSet
s.
将对象文字添加到WeakSet
s绝对没有意义。
What is the practical use of WeakSet if we cannot even iterate through it nor get the current size?
如果我们甚至无法遍历它也无法获得当前大小,那么 WeakSet 的实际用途是什么?
All you can get is one bit of information: Is the object (or generically, value) contained in the set?
你所能得到的只是一点信息:对象(或一般来说,值)是否包含在集合中?
This can be useful in situations where you want to "tag" objects without actually mutating them (setting a property on them). Lots of algorithms contain some sort of "if x
was already seen" condition (a JSON.stringify
cycle detection might be a good example), and when you work with user-provided values the use of a Set
/WeakSet
would be advisable. The advantage of a WeakSet
here is that its contents can be garbage-collected while your algorithm is still running, so it helps to reduce memory consumption (or even prevents leaks) when you are dealing with lots of data that is lazily (possibly even asynchronously) produced.
这在您想要“标记”对象而不实际改变它们(在它们上设置属性)的情况下很有用。许多算法包含某种“如果x
已经看到”条件(JSON.stringify
循环检测可能是一个很好的例子),并且当您使用用户提供的值时,建议使用Set
/ WeakSet
。a WeakSet
here的优点是它的内容可以在您的算法仍在运行时被垃圾收集,因此当您处理大量懒惰(甚至可能是异步的)数据时,它有助于减少内存消耗(甚至防止泄漏)产生。
回答by Benjamin Gruenbaum
This is a really hard question. To be completely honest I had no idea in the context of JavaScript so I asked in esdiscussand got a convincing answer from Domenic.
这真是一个很难回答的问题。老实说,我对 JavaScript 的上下文一无所知,所以我在 esdiscuss 中提问,并从Domenic那里得到了令人信服的回答。
WeakSets are useful for securityand validationreasons. If you want to be able to isolate a piece of JavaScript. They allow you to tagan object to indicate it belongs to a special set of object.
WeakSets 出于安全和验证的原因很有用。如果您希望能够隔离一段 JavaScript。它们允许您标记一个对象以表明它属于一组特殊的对象。
Let's say I have a class ApiRequest
:
假设我有一堂课ApiRequest
:
class ApiRequest {
constructor() {
// bring object to a consistent state, use platform code you have no cirect access to
}
makeRequest() {
// do work
}
}
Now, I'm writing a JavaScript platform - my platform allows you to run JavaScript to make calls - to make those calls you need a ApiRequest
- I only want you to make ApiRequest
s with the objects I give you so you can't bypass any constraints I have in place.
现在,我正在编写一个 JavaScript 平台——我的平台允许你运行 JavaScript 来进行调用——进行那些你需要的调用ApiRequest
——我只希望你ApiRequest
使用我给你的对象来创建s,这样你就不能绕过任何限制我有到位。
However, at the moment nothing is stopping you from doing:
然而,目前没有什么能阻止你做:
ApiRequest.prototype.makeRequest.call(null, args); // make request as function
Object.create(ApiRequest.prototype).makeRequest(); // no initialization
function Foo(){}; Foo.prototype = ApiRequest.prototype; new Foo().makeRequest(); // no super
And so on, note that you can't keep a normal list or array of ApiRequest
objects since that would prevent them from being garbage collected. Other than a closure, anything can be achieved with public methods like Object.getOwnPropertyNames
or Object.getOwnSymbols
. So you one up me and do:
依此类推,请注意您不能保留一个普通的ApiRequest
对象列表或数组,因为这会阻止它们被垃圾收集。除了闭包,任何事情都可以通过公共方法实现,比如Object.getOwnPropertyNames
或Object.getOwnSymbols
。所以你一个我,做:
const requests = new WeakSet();
class ApiRequest {
constructor() {
requests.add(this);
}
makeRequest() {
if(!request.has(this)) throw new Error("Invalid access");
// do work
}
}
Now, no matter what I do - I must hold a valid ApiRequest
object to call the makeRequest
method on it. This is impossible without a WeakMap/WeakSet.
现在,无论我做什么 - 我必须持有一个有效的ApiRequest
对象来调用makeRequest
它的方法。如果没有 WeakMap/WeakSet,这是不可能的。
So in short - WeakMaps are useful for writing platforms in JavaScirpt. Normally this sort of validation is done on the C++ side but adding these features will enable moving and making things in JavaScript.
所以简而言之 - WeakMaps 对于在 JavaScirpt 中编写平台很有用。通常这种验证是在 C++ 端完成的,但添加这些功能将允许在 JavaScript 中移动和制作东西。
(Of course, everything a WeakSet
does a WeakMap
that maps values to true
can also do, but that's true for any map/set construct)
(当然,将值映射到的aWeakSet
所做的一切也可以做,但对于任何 map/set 构造都是如此)WeakMap
true
(Like Bergi's answer suggests, there is never a reason to add an object literal directly to a WeakMap
or a WeakSet
)
(就像 Bergi 的回答所暗示的那样,永远没有理由将对象文字直接添加到 aWeakMap
或 a WeakSet
)
回答by TaoPR
By definition, WeakSet
has only three key functionalities
根据定义,WeakSet
只有三个关键功能
- Weakly link an object into the set
- Remove a link to an object from the set
- Check if an object has already been linked to the set
- 将对象弱链接到集合中
- 从集合中删除指向对象的链接
- 检查对象是否已链接到集合
Sounds more pretty familiar?
听起来更耳熟?
In some application, developers may need to implement a quick way to iterate through a series of data which is polluted by lots and lots of redundancy but you want to pick only ones which have not been processed before (unique). WeakSet could help you. See an example below:
在某些应用程序中,开发人员可能需要实现一种快速的方法来迭代一系列被大量冗余污染的数据,但您只想选择以前没有处理过的(唯一的)。WeakSet 可以帮助你。请参阅下面的示例:
var processedBag = new WeakSet();
var nextObject = getNext();
while (nextObject !== null){
// Check if already processed this similar object?
if (!processedBag.has(nextObject)){
// If not, process it and memorize
process(nextObject);
processedBag.add(nextObject);
}
nextObject = getNext();
}
One of the best data structure for application above is Bloom filterwhich is very good for a massive data size. However, you can apply the use of WeakSetfor this purpose as well.
上述应用程序的最佳数据结构之一是布隆过滤器,它非常适合海量数据。但是,您也可以为此目的使用WeakSet。
回答by Mike Robinson
A "weak" set or map is useful when you need to keep an arbitrary collection of things but you don't want their presence in the collection from preventing those things from being garbage-collected if memory gets tight. (If garbage collection doesoccur, the "reaped" objects will silently disappear from the collection, so you can actually tell if they're gone.)
“弱”集合或映射在您需要保留任意集合的东西时很有用,但您不希望它们出现在集合中,从而在内存紧张时阻止这些东西被垃圾收集。(如果确实发生了垃圾收集,“已收割”的对象将从收集中悄悄消失,因此您实际上可以判断它们是否消失了。)
They are excellent, for example, for use as a look-aside cache: "have I already retrieved this record, recently?"Each time you retrieve something, put it into the map, knowing that the JavaScript garbage collectorwill be the one responsible for "trimming the list" for you, and that it will automatically do so in response to prevailing memory conditions (which you can't reasonably anticipate).
例如,它们非常适合用作后备缓存:“我最近是否已经检索过此记录?” 每次你检索到一些东西时,把它放入地图中,知道JavaScript 垃圾收集器将负责为你“修剪列表”,并且它会自动这样做以响应普遍的内存条件(你可以' t 合理预期)。
The only drawback is that these types are not "enumerable." You can't iterate over a list of entries – probably because this would likely "touch" those entries and so defeat the purpose. But, that's a small price to pay (and you could, if need be, "code around it").
唯一的缺点是这些类型不是“可枚举的”。您无法遍历条目列表 - 可能是因为这可能会“触及”这些条目,从而无法达到目的。但是,这是一个很小的代价(如果需要,您可以“围绕它编写代码”)。
回答by jgmjgm
WeakSet is a simplification of WeakMap for where your value is always going to be boolean true. It allows you to tag JavaScript objects so to only do something with them once or to maintain their state in respect to a certain process. In theory as it doesn't need to hold a value it should use a little less memory and perform slightly faster than WeakMap.
WeakSet 是 WeakMap 的简化版,因为您的值始终为布尔值 true。它允许您标记 JavaScript 对象,以便只对它们执行一次操作或针对某个进程维护它们的状态。理论上,因为它不需要保存一个值,所以它应该使用更少的内存并且比 WeakMap 执行速度略快。
var [touch, untouch] = (() => {
var seen = new WeakSet();
return [
value => seen.has(value)) || (seen.add(value), !1),
value => !seen.has(value) || (seen.delete(value), !1)
];
})();
function convert(object) {
if(touch(object)) return;
extend(object, yunoprototype); // Made up.
};
function unconvert(object) {
if(untouch(object)) return;
del_props(object, Object.keys(yunoprototype)); // Never do this IRL.
};
回答by Willem van der Veen
Your console was probably incorrectly showing the contents due to the fact that the garbage collection did not take place yet. Therefore since the object wasn't garbage collected it would show the object still in weakset.
由于垃圾收集尚未发生,您的控制台可能会错误地显示内容。因此,由于对象没有被垃圾收集,所以它会显示对象仍然处于弱集状态。
If you really want to see if a weakset still has a reference to a certain object then use the WeakSet.prototype.has()
method. This method, as the name implies returns a boolean
indicating wether the object still exists in the weakset.
如果您真的想查看弱集是否仍然具有对某个对象的引用,请使用该WeakSet.prototype.has()
方法。这个方法,顾名思义,返回一个boolean
指示对象是否仍然存在于弱集中。
Example:
例子:
var weakset = new WeakSet(),
numbers = [1, 2, 3];
weakset.add(numbers);
weakset.add({name: "Charlie"});
console.log(weakset.has(numbers));
numbers = undefined;
console.log(weakset.has(numbers));