关于地图和弱地图已经存在一些问题,例如: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;
答案 0 :(得分:10)
这包含在规范的§23.3中:
如果一个被用作
WeakMap
键/值对的键的对象只能通过跟随在该WeakMap
内开始的一系列引用来访问,那么该键/值对是无法访问,会自动从WeakMap
中删除。
因此弱映射中的条目,如果它们的键没有被其他任何东西引用,将在某个时候通过垃圾收集来回收。
相比之下,Map
拥有对其键的强引用,如果地图是引用它们的唯一内容,则会阻止它们被垃圾收集。
MDN puts it like this:
WeakMap
中的键被弱化。这意味着,如果没有对密钥的其他强引用,那么整个条目将被垃圾收集器从WeakMap
中删除。
WeakSet
也是如此。
......在哪种情况下我应该支持使用这种数据结构?
您不希望使用密钥来阻止该密钥被垃圾收集的任何情况。
可能使用此功能的一个示例是具有特定于实例的信息,该信息对于实例来说是真正私有的,如下所示:
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
不会防止实例被垃圾收集;相反,实例键入的条目将从地图中删除。
上述哪些数据结构将产生相同/相似的结果:
let hash = Object.create(null); hash[index] = something;
这将最接近Map
,因为字符串index
(属性名称)将由对象中的强引用持有(如果没有其他内容,则不会回收它及其关联的属性引用它)。