问题
I am experiencing with JavaScript weakmaps, after trying this code in google chrome developer console, running with --js-flags="--expose-gc", I don't understand why the weakmap keep having a reference to a.b if a is 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?
回答1:
In your example code, you're not releasing your a
variable. It's a top level var that never goes out of scope and never gets explicitly de-referenced, so it stays in the WeakMap. WeakMap/WeakSet releases objects once there are no more references to it in your code. In your example, if you console.log(a)
after one of your gc()
calls, you'd still expect a
to be alive, right?
So here's a working example showing WeakSet in action and how it'll delete an entry once all references to it are gone: 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);
Note that having Chrome dev tools opened prevents some objects from getting garbage collected, which makes seeing this in action more difficult than expected :)
来源:https://stackoverflow.com/questions/38203446/javascript-weakmap-keep-referencing-gced-objects