JavaScript WeakMap 不断引用 gc 对象

Mat*_*ati 7 javascript garbage-collection weakmap ecmascript-6

我正在使用 JavaScript 弱图,在 google chrome 开发者控制台中尝试此代码后,使用 --js-flags="--expose-gc" 运行,我不明白为什么弱图一直引用 ab 如果 a 是gc'ed。

var a = {listener: function(){ console.log('A') }}
a.b = {listener: function(){ console.log('B') }}

var map = new WeakMap()

map.set(a.b, [])
map.set(a, [a.b.listener])

console.log(map) // has both a and a.b

gc()
console.log(map) // still have both a and a.b

a = undefined
gc()
console.log(map) // only have a.b: why does still have a reference to a.b? Should'nt be erased?
Run Code Online (Sandbox Code Playgroud)

ccn*_*kes 5

更新 2/2020

当我现在运行此代码时,它按预期工作。我认为打开控制台会导致对象被保留在以前版本的 Chrome 中,但现在不是。重新分配保存对象引用的变量的值将导致该对象被垃圾收集(假设没有其他对象引用它)。


在您的示例代码中,您没有释放a变量。它是一个永远不会超出范围并且永远不会被明确取消引用的顶级 var,因此它保留在 WeakMap 中。WeakMap/WeakSet 一旦在你的代码中不再引用它就会释放对象。在您的示例中,如果您console.log(a)打完一个gc()电话,您仍然希望a活着,对吗?

因此,这里有一个工作示例,显示了 WeakSet 的运行情况以及一旦对它的所有引用都消失了它将如何删除条目:https ://embed.plnkr.co/cDqi5lFDEbvmjl5S19Wr/

const wset = new WeakSet();

// top level static var, should show up in `console.log(wset)` after a run
let arr = [1];
wset.add(arr);

function test() {
  let obj = {a:1}; //stack var, should get GCed
  wset.add(obj);
}

test();

//if we wanted to get rid of `arr` in `wset`, we could explicitly de-reference it
//arr = null;

// when run with devtools console open, `wset` always holds onto `obj`
// when devtools are closed and then opened after, `wset` has the `arr` entry,
// but not the `obj` entry, as expected
console.log(wset);
Run Code Online (Sandbox Code Playgroud)

请注意,打开 Chrome 开发工具会阻止某些对象被垃圾收集,这使得在操作中看到这一点比预期的要困难:)