已经有一些关于 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/

10-09 14:49