Как наблюдать за сборкой мусора из WeakMap в Javascript? - PullRequest
0 голосов
/ 06 февраля 2020

Насколько я понимаю, WeakMap говорит, что «ссылки на объекты в коллекции хранятся слабо. Если нет другой ссылки на объект, сохраненный в WeakMap, они могут быть удалены мусором».

Почему следующие пары ключ / значение по-прежнему появляются в WeakMap после удаления ссылок? Разве WeakMap не должен быть пустым?

let dog1 = {name: 'Snickers'};
let dog2 = {name: 'Sunny'};

var strong = new Map();
var weak = new WeakMap();


strong.set(dog1, 'Snickers is the best!');
strong.set(dog2, 'Sunny is the 2nd best!');
weak.set(dog1, 'Snickers is the best!');
weak.set(dog2, 'Sunny is the 2nd best!');

dog1 = null;
dog2 = null;

console.log(strong);
console.log(weak);

/*
Output
Map(2) {{…} => "Snickers is the best!", {…} => "Sunny is the 2nd best!"}
WeakMap {{…} => "Snickers is the best!", {…} => "Sunny is the 2nd best!"}
*/

setTimeout(function(){
console.log("1200ms later... waiting for garbarge collection");
console.log(strong);
console.log(weak);
}, 1200);

/*
Output
Map(2) {{…} => "Snickers is the best!", {…} => "Sunny is the 2nd best!"}
WeakMap {{…} => "Snickers is the best!", {…} => "Sunny is the 2nd best!"}
*/

Ответы [ 2 ]

0 голосов
/ 08 февраля 2020

После исправления ошибок, указанных @Amadan @Bergi @Geeganage, следующий код дает желаемый результат в Safari и Chrome, при этом сборка мусора запускается после одного из нескольких вновь добавленных таймаутов. В результате окончательная версия WeakMap не содержит ссылок.

let dog1 = {name: 'Snickers'};
let dog2 = {name: 'Sunny'};

var strong = new Map();
var weak = new WeakMap();


strong.set(dog2, 'Sunny is the 2nd best!');
weak.set(dog1, 'Snickers is the best!');

dog1 = null;
dog2 = null;

console.log(strong);
console.log(weak);

/*
Output
[Log] Map {{name: "Sunny"} => "Sunny is the 2nd best!"} (1)
[Log] WeakMap {{name: "Snickers"} => "Snickers is the best!"} (1)
*/

setTimeout(function(){
console.log("1200ms later... waiting for garbarge collection");
console.log(strong);
console.log(weak);
}, 1200);

setTimeout(function(){
console.log("3200ms later... waiting for garbarge collection");
console.log(strong);
console.log(weak);
}, 3200);

setTimeout(function(){
console.log("6200ms later... waiting for garbarge collection");
console.log(strong);
console.log(weak);
}, 6200);

setTimeout(function(){
console.log("12200ms later... waiting for garbarge collection");
console.log(strong);
console.log(weak);
}, 12200);

/* 
Output (eventually)
[Log] Map {{name: "Sunny"} => "Sunny is the 2nd best!"} (1)
[Log] WeakMap {} (0)
*/

Поскольку сборка мусора не гарантируется, если вы вставляете код в консоль во время прокрутки сайта JS Heavy, G C может действительно работать после первого таймаута.

0 голосов
/ 06 февраля 2020

Здесь вы сначала создали два отдельных javascript объекта, которые называются (имена ссылочных переменных) dog1 и dog2:

    let dog1 = {name: 'Snickers'};
    let dog2 = {name: 'Sunny'};

И затем вы создали два разных объекта Map, которые называются сильными и слабыми.

    var strong = new Map();
    var weak = new WeakMap();

Здесь вы устанавливаете только значение ссылочной переменной в качестве ключа для обеих карт. И этот объект карты является отдельным объектом, и он больше не имеет никакой связи с этими ссылочными переменными «dog1» и «dog2» после того, как эти значения установлены в качестве ключей объектов этой карты.

   strong.set(dog1, 'Snickers is the best!'); // Here after value of dog1 doesn't affect map "strong"
   strong.set(dog2, 'Sunny is the 2nd best!'); // Here after value of dog2 doesn't affect map "strong"
   weak.set(dog1, 'Snickers is the best!'); // Here after value of dog1 doesn't affect map "weak"
   weak.set(dog2, 'Sunny is the 2nd best!'); // Here after value of dog2 doesn't affect map "weak"

Таким образом, после помещения значений этих переменных в карты, даже если вы присвоите нулевые значения этим ссылочным переменным, это не повлияет на карту. Потому что они являются отдельными объектами и больше не зависят друг от друга.

   dog1 = null;
   dog2 = null;

Итак, даже если вы проверите это через 1200 мс, результат также будет таким же. Потому что внесение изменений (путем присвоения значения NULL) в эти ссылочные переменные не влияет на карту.

   setTimeout(function(){
     console.log("1200ms later... waiting for garbarge collection");
     console.log(strong);
     console.log(weak);
   }, 1200);

А также у вас все еще есть сильные и слабые ссылочные переменные, поэтому они по-прежнему не подходят для сбора мусора.

Надеюсь, что следующая ссылка поможет вам изучить сборку мусора в JavaScript:

https://dzone.com/articles/memory-management-and-garbage-collection-in-javasc

...