3

我的理解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!"}
*/
4

3 回答 3

1

在修复了@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 繁重的网站时将代码粘贴到控制台中,GC 可能实际上会在第一次超时后运行。

于 2020-02-07T21:48:12.773 回答
0

In here you firstly created two seperate javascript objects called(reference variable names) dog1 and dog2:

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

And then you've created two different Map objects called strong and weak.

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

In here you only set the value of the reference variable as the key for both Maps. And that map object is a seperate object and it doesn't have any connection with those reference variables "dog1" and "dog2" anymore after those values are put as the keys of that map objects.

   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"

So, after put the values of these variables in to the maps, even you assign null value to those reference variables it doesn't affect the map. Because they are seperate objects and don't depend on each other anymore.

   dog1 = null;
   dog2 = null;

So, even you check it after 1200ms also the result is same. Because making changes(by assigning null) to those reference variables doesn't affect the map.

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

And also you still have a reference variables strong and weak,so they are not still elegible for garbage collection.

希望以下链接能帮助您学习 JavaScript 中的垃圾收集:

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

于 2020-02-06T09:16:55.953 回答
0

您的代码完全没问题,问题是它不能保证向您显示您想要的结果,当 JS 引擎决定是时候这样做时就会发生垃圾收集......我们无法定义它执行它的时间。这就是为什么WeakMap不支持迭代和方法keys()的原因values()entries()因为我们不知道这些键和值是否存在......换句话说,我们不知道当时是否发生了垃圾收集。如果我们有一个松散的引用,并且它还没有被垃圾收集,这些方法会给我们错误的结果,这就是为什么它们被禁用的原因WeakMap

于 2021-03-14T09:07:19.767 回答