JavaScript WeakMap 不断引用 gc 对象
JavaScript WeakMap keep referencing gc'ed objects
我正在使用 JavaScript weakmaps,在 google chrome 开发者控制台中尝试此代码后,运行 --js-flags="--expose- gc",我不明白为什么 weakmap 在 gc 后一直引用 a.b。
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?
2020 年 2 月更新
当我现在 运行 这段代码时,它按预期工作。我认为打开控制台会导致对象在 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);
请注意,打开 Chrome 开发工具会阻止某些对象被垃圾回收,这使得实际操作比预期更困难:)
我正在使用 JavaScript weakmaps,在 google chrome 开发者控制台中尝试此代码后,运行 --js-flags="--expose- gc",我不明白为什么 weakmap 在 gc 后一直引用 a.b。
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?
2020 年 2 月更新
当我现在 运行 这段代码时,它按预期工作。我认为打开控制台会导致对象在 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);
请注意,打开 Chrome 开发工具会阻止某些对象被垃圾回收,这使得实际操作比预期更困难:)