2016-07-05 33 views
4

我在使用JavaScript弱点映射时,在谷歌浏览器开发人员控制台中尝试此代码后,运行时使用--js-flags =“ - expose-gc”,我不明白为什么如果a被gc化了,那么弱映射就继续引用ab。JavaScript WeakMap继续引用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? 
+0

这看起来像一个bug给我。如果你多次使用gc(),它会持久吗?如果是这样,那么你应该用V8报告它。 – Bergi

回答

1

在您的示例代码中,您不会发布您的a变量。这是一个顶级变量,永远不会超出范围,并且永远不会被明确地取消引用,所以它保留在WeakMap中。一旦在代码中没有更多的引用,WeakMap/WeakSet就会释放对象。在你的例子中,如果你在gc()之一呼叫之后console.log(a),你仍然期望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浏览器开发工具,打开可以防止因垃圾某些对象收集,这使得看到这在行动比预期更难:)