Javascript /垃圾收集器中的循环引用

jAn*_*ndy 40 javascript garbage-collection memory-leaks circular-reference

有人可以详细解释Javascript引擎如何处理循环引用?浏览器甚至node.js之间有很大的区别吗?

我所说的是对象内部的显式反向/下一个引用.例如:

var objA = {
    prop: "foo",
    next: null
};

var objB = {
    prop: "foo",
    prev: null
};

objA.next = objB;
objB.prev = objA;
Run Code Online (Sandbox Code Playgroud)

我们走了.如果我们这样做,console.log( objA )我们可以看到我们创造了一个无限链.最大的问题是,这是不是很糟糕?未明确清除时是否会造成内存泄漏?

所以我们必须这样做

objA.next = null;
objB.prev = null;
Run Code Online (Sandbox Code Playgroud)

或者垃圾收集者会照顾我们这样的星座吗?

jal*_*alf 64

任何半体面的垃圾收集器都会处理周期.

如果你进行天真的引用计数,周期只是一个问题.

大多数垃圾收集器不进行重新计数(因为它无法处理循环,因为它效率低).相反,他们只是遵循他们可以找到的每个引用,从"根"(通常是全局变量和基于堆栈的变量)开始,并将他们可以找到的所有内容标记为"可达".

然后他们只是回收所有其他记忆.

循环没有问题,因为它们只是意味着将多次到达同一节点.在第一次之后,节点将被标记为"可达",因此GC将知道它已经存在,并跳过该节点.

基于引用计数的更原始的GC通常实现用于检测和中断循环的算法.

简而言之,这不是你必须担心的事情.我似乎记得IE6的Javascript GC实际上无法处理周期(我可能是错的,自从我读它以来已经有一段时间了,而且自从我触及IE6以来已经有很长时间了),但在任何现代实现中,它都不是问题.

垃圾收集器中的重点是抽象出内存管理.如果您必须自己完成这项工作,那么您的GC就会崩溃.

有关现代垃圾收集和使用的标记和扫描算法的更多信息,请参阅MDN.

  • @Sandro再次阅读我的回答.:)一个理智的GC处理循环就好了.比IE6更新的一切都可以被认为是理智的.如果您需要支持IE6,那么您必须担心它的循环处理中断.显然,谷歌的指南是在假设必须支持这种破碎的浏览器的情况下编写的,因此他们必须跳过一些额外的环节. (2认同)
  • Douglas Crockford [提及](http://javascript.crockford.com/memory/leak.html)也有[IE6缺陷](http://support.microsoft.com/kb/929874/)。我认为,如今,我们可以认为它与大多数Web应用程序无关。 (2认同)