已经有一些关于 map 和弱 map 的问题,例如:What's the difference between ES6 Map and WeakMap?,但是我想问一下在哪种情况下我应该赞成使用这些数据结构?或者当我偏爱一个时,应该考虑什么?
数据结构示例来自: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
奖金。以上哪种数据结构会产生相同/相似的结果:
let hash = object.create(null); hash[index] = something;
最佳答案
规范的§23.3对此进行了介绍:
因此,弱映射中的条目(如果没有其他键引用它们的键)将在某个时候被垃圾回收回收。
相比之下,Map
对它的键有很强的引用,如果唯一的引用是映射,则可以防止它们被垃圾回收。
MDN puts it like this:
和WeakSet
一样。
在任何情况下,如果您不希望使用键有一个映射/集合,以防止该键被垃圾回收。
何时使用此功能的一个示例是拥有特定于实例的信息,而该信息实际上是该实例的私有(private)信息,如下所示:
let Thing = (() => {
var privateData = new WeakMap();
class Thing {
constructor() {
privateData[this] = {
foo: "some value"
};
}
doSomething() {
console.log(privateData[this].foo);
}
}
return Thing;
})();
该作用域函数之外的代码无法访问
privateData
中的数据。该数据由实例本身进行键控。如果没有WeakMap
,您将无法做到这一点,因为如果您这样做会导致内存泄漏,那么您的Thing
实例将永远无法清除。但是WeakMap
仅持有弱引用,因此,如果使用Thing
实例的代码已完成并释放其对该实例的引用,则WeakMap
不会阻止对该实例进行垃圾回收;而是将实例键控的条目从映射中删除。这将最接近
Map
,因为字符串index
(属性名称)将由对象中的强引用保存(如果没有其他引用,则不会收回它及其关联的属性)。关于javascript - ES6 Set,WeakSet,Map和WeakMap,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32710432/