2016-07-05 31 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瀏覽器開發工具,打開可以防止因垃圾某些對象收集,這使得看到這在行動比預期更難:)