7

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
  • This looks like a bug to me. Does it persist if you gc() multiple times? If so then you should probably report it with V8. Commented Jul 5, 2016 at 12:49

1 Answer 1

6

UPDATE 2/2020

When I run this code now, it works as expected. I think having the console open was causing objects to be held onto in previous versions of Chrome but not now. Reassigning the value of a variable that holds a reference to an object will cause that object to be garbage collected (assuming nothing else has a reference to it).


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 :)

Sign up to request clarification or add additional context in comments.

3 Comments

"you're not releasing your a variable" I think setting the variable value to undefined should be enough. If it is now, can you please explain why?
@Suma when I run the OP's code now, it works as expected. I think having the console open was causing objects to be held onto in previous versions of Chrome but not now. 🤷‍♂️
Interesting to know. Still I am afraid I have to insist the leading sentence "In your example code, you're not releasing your a variable. It's a top level var that never goes out of scope" is wrong, as setting the variable to null or undefined (or any other value) should make the original value of the variable eligible for collection.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.