Javascript ECMAScript 6:带有WeakSet参数的console.log的奇怪行为
如何解释以下内容: 如果我们对第一次调用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
集合。[[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,我们不应该在意)。