如何在Javascript中观察弱映射的垃圾收集?

如何在Javascript中观察弱映射的垃圾收集?,javascript,weakmap,Javascript,Weakmap,我对WeakMap的理解是,“对集合中对象的引用保存得很弱。如果对WeakMap中存储的对象没有其他引用,则可以对它们进行垃圾收集。” 为什么删除引用后,WeakMap中仍会出现以下键/值对?WeakMap不应该是空的吗 let dog1 = {name: 'Snickers'}; let dog2 = {name: 'Sunny'}; var strong = new Map(); var weak = new WeakMap(); strong.set(dog1, 'Snickers

我对
WeakMap
的理解是,“对集合中对象的引用保存得很弱。如果对WeakMap中存储的对象没有其他引用,则可以对它们进行垃圾收集。”

为什么删除引用后,WeakMap中仍会出现以下键/值对?WeakMap不应该是空的吗

let dog1 = {name: 'Snickers'};
let dog2 = {name: 'Sunny'};

var strong = new Map();
var weak = new WeakMap();


strong.set(dog1, 'Snickers is the best!');
strong.set(dog2, 'Sunny is the 2nd best!');
weak.set(dog1, 'Snickers is the best!');
weak.set(dog2, 'Sunny is the 2nd best!');

dog1 = null;
dog2 = null;

console.log(strong);
console.log(weak);

/*
Output
Map(2) {{…} => "Snickers is the best!", {…} => "Sunny is the 2nd best!"}
WeakMap {{…} => "Snickers is the best!", {…} => "Sunny is the 2nd best!"}
*/

setTimeout(function(){
console.log("1200ms later... waiting for garbarge collection");
console.log(strong);
console.log(weak);
}, 1200);

/*
Output
Map(2) {{…} => "Snickers is the best!", {…} => "Sunny is the 2nd best!"}
WeakMap {{…} => "Snickers is the best!", {…} => "Sunny is the 2nd best!"}
*/

在这里,您首先创建了两个单独的javascript对象(reference) 变量名)dog1和dog2:

    let dog1 = {name: 'Snickers'};
    let dog2 = {name: 'Sunny'};
然后创建了两个不同的贴图对象,分别称为“强”和“弱”

    var strong = new Map();
    var weak = new WeakMap();
在这里,您仅将引用变量的值设置为这两个变量的键 地图。地图对象是一个独立的对象,它没有任何 与那些参考变量“dog1”和“dog2”之间的连接 值作为映射对象的键放置

   strong.set(dog1, 'Snickers is the best!'); // Here after value of dog1 doesn't affect map "strong"
   strong.set(dog2, 'Sunny is the 2nd best!'); // Here after value of dog2 doesn't affect map "strong"
   weak.set(dog1, 'Snickers is the best!'); // Here after value of dog1 doesn't affect map "weak"
   weak.set(dog2, 'Sunny is the 2nd best!'); // Here after value of dog2 doesn't affect map "weak"
因此,在将这些变量的值放入映射后,即使您指定null 对于那些引用变量,它不会影响映射。因为他们是 分离对象,不再相互依赖

   dog1 = null;
   dog2 = null;
所以,即使你在1200毫秒后检查,结果也是一样的。因为制造 对这些引用变量的更改(通过指定null)不会影响映射

   setTimeout(function(){
     console.log("1200ms later... waiting for garbarge collection");
     console.log(strong);
     console.log(weak);
   }, 1200);
还有一个参考变量,它的强弱,所以它们不是 仍然可以进行垃圾收集

希望下面的链接能帮助您学习垃圾收集 JavaScript:


在修复了@Amadan@Bergi@Geeganage指出的错误后,以下代码以Safari和Chrome提供了所需的输出,并在几个新添加的超时之一后运行垃圾收集。导致最终WeakMap不保留任何引用

let dog1 = {name: 'Snickers'};
let dog2 = {name: 'Sunny'};

var strong = new Map();
var weak = new WeakMap();


strong.set(dog2, 'Sunny is the 2nd best!');
weak.set(dog1, 'Snickers is the best!');

dog1 = null;
dog2 = null;

console.log(strong);
console.log(weak);

/*
Output
[Log] Map {{name: "Sunny"} => "Sunny is the 2nd best!"} (1)
[Log] WeakMap {{name: "Snickers"} => "Snickers is the best!"} (1)
*/

setTimeout(function(){
console.log("1200ms later... waiting for garbarge collection");
console.log(strong);
console.log(weak);
}, 1200);

setTimeout(function(){
console.log("3200ms later... waiting for garbarge collection");
console.log(strong);
console.log(weak);
}, 3200);

setTimeout(function(){
console.log("6200ms later... waiting for garbarge collection");
console.log(strong);
console.log(weak);
}, 6200);

setTimeout(function(){
console.log("12200ms later... waiting for garbarge collection");
console.log(strong);
console.log(weak);
}, 12200);

/* 
Output (eventually)
[Log] Map {{name: "Sunny"} => "Sunny is the 2nd best!"} (1)
[Log] WeakMap {} (0)
*/

由于垃圾收集不能保证运行,如果您在滚动JS heavy网站时将代码粘贴到控制台,GC可能会在第一次超时后运行。

您的代码完全正常,问题是它不能保证向您显示所需的结果,当JS引擎决定是时候进行垃圾收集时,就会发生垃圾收集。。。我们不能确定它做这件事的时间。这就是为什么
WeakMap
不支持迭代和方法
keys()
values()
entries()
,因为我们不知道这些键和值是否存在。。。换句话说,我们不知道垃圾收集是否发生在那个时刻。
如果我们有一个松散的引用,并且它还没有被垃圾收集,这些方法会给我们错误的结果,这就是为什么它们被禁用,用于
WeakMap

您在
strong
中仍然有一个引用,所以它们不能被垃圾收集。“如何观察…”-您不能。即使在修复错误后,垃圾收集也不能保证运行。@Bergi没有保证,但上述内容在修复错误后显示垃圾收集行为方面似乎相当一致。只要不依赖它在生产代码中工作,它就可以用于学习目的(这似乎就是这个问题的目的)。@JLRishe现在这样做了吗?他们一定已经改变了这一点,.@Bergi如果我删除第二个
strong.set
行并在Chrome的控制台中运行代码,WeakMap将显示为在
setTimeout
之前包含dog2,而在超时之后不包含它。您链接到的问题没有使用超时,因此该问题中的代码可能在垃圾收集之前记录了weakmap。这仍然不能保证向您显示所需的结果,当JS引擎看到是时候进行垃圾收集时,垃圾收集就会发生。。。我们无法定义垃圾收集的时间。这完全不是真的,这里唯一的问题是我们不知道垃圾收集何时发生。我们只知道,当引擎进行垃圾收集时,WeakMap将释放未引用的密钥