Javascript ECMAScript 6:带有WeakSet参数的console.log的奇怪行为

Javascript ECMAScript 6:带有WeakSet参数的console.log的奇怪行为,javascript,ecmascript-6,Javascript,Ecmascript 6,如何解释以下内容: 如果我们对第一次调用console.log进行注释,则集合。[[Entries]].length将是1,如果没有注释集合。[[Entries]].length=0 输出:长度=0 let mySet = new WeakSet(), key = {}; mySet.add( key ); // add the object to the set //console.log( mySet ); // uncommenting will chang

如何解释以下内容: 如果我们对第一次调用console.log进行注释,则
集合。[[Entries]].length
将是
1
,如果没有注释
集合。[[Entries]].length
=
0

输出:长度=0

let mySet = new WeakSet(),
key = {};

mySet.add( key );           // add the object to the set

//console.log( mySet );     // uncommenting will change the [[Entries]].length
key = null;                 // delete key
console.log( mySet );       // [[Entries]].length: 0
输出:长度=1

let mySet = new WeakSet(),
key = {};

mySet.add( key );           // add the object to the set

console.log( mySet );         // commenting will change the [[Entries]].length
key = null;                 // delete key
console.log( mySet );       // [[Entries]].length: 1
另一个版本:如果我们在第二种情况下(脚本末尾)再添加一个
console.log(mySet)
<代码>[[Entries]]。长度将为
0


一位评论员提到它应该是垃圾收集器。但它在真实脚本中的表现如何?如果我使用一次调用对象(没有第二次),它是否会被删除(在对象设置为
null
之后)?

这一点也不奇怪,这只是弱集合的标准行为。[[Entries]]是一个内部插槽,具有非常依赖于实现的行为,甚至可能不存在于实际实现中,而只是显示在调试器中


一旦覆盖对象的
引用,它就会被垃圾收集,并且不会被
mySet
持有。
console.log
的自定义行为显然创建了对对象的另一个引用(因为您仍然可以在控制台中与它进行交互),因此它不会被垃圾收集,并且仍然显示在列表中。

为什么这样奇怪?您正在将(waaay)键设置为对象引用。然后你;我们正在删除该引用。不过,我个人希望对这种行为进行解释。@Ivar我已经更改了变量名(我还没有学习setters),但奇怪的情况仍然存在。我对代码做了一点修改,所以任何人都可以复制并粘贴它。@evolutionxbox,因为第二个console.log调用仍然是在将
key
赋值为
null
之后进行的。它应该输出相同的结果,但是它没有。再看一次我的解释,为什么应该是一样的?您正在将
键设置为对
{}
的引用。在我看来,一旦您将
键设置为
未定义
,它就会从
mySet
中删除。这很可能与垃圾收集器何时启动有关。但是为什么第二次调用
控制台.log
会让垃圾收集器删除该引用呢?第二个
console.log
在这种情况下应该进行新引用,并且对象应该继续存在,不是吗?@VadimCherepenichev在
key=null
语句之前,对象被强引用,并且必须位于WeakSet`(其中
console.log
调用会找到它)。在该语句之后,假设
key
变量是对该对象的最后一个引用,它可以被垃圾回收(但可能尚未被回收)。现在记录集合时,没有任何东西表明对象需要存在或再次可引用。当不再有引用时,它不会“创建新引用”。(当然,所有这些都取决于实现,可能
console.log
强制GC或不强制GC,我们不应该在意)。