JavaScript WeakMap продолжает ссылаться на gc'ed объекты
Я испытываю слабые карты JavaScript, после того, как я попробовал этот код в консоли разработчика Google Chrome, запустив с параметром --js-flags="- expose-gc", я не понимаю, почему у карты слабых карт есть ссылка на ab, если a 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 ответ
В вашем примере кода вы не выпускаете 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 не позволяют собирать мусор некоторым объектам, что затрудняет просмотр этого в действии.