ES6 Set,WeakSet,Map和WeakMap

时间:2015-09-22 07:04:50

标签: javascript ecmascript-6

关于地图和弱地图已经存在一些问题,例如: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;

1 个答案:

答案 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(属性名称)将由对象中的强引用持有(如果没有其他内容,则不会回收它及其关联的属性引用它)。