有人可以详细解释Javascript引擎如何处理循环引用吗?浏览器甚至node.js之间是否存在很大差异?
我所说的是对象中明确的后向/下一个引用。例如:
var objA = {
prop: "foo",
next: null
};
var objB = {
prop: "foo",
prev: null
};
objA.next = objB;
objB.prev = objA;
我们走了。如果我们做console.log( objA )
,我们可以看到我们创建了一个无限链。
最大的问题是,这是不是很糟糕?未明确清理时是否会造成内存泄漏?
所以我们必须
objA.next = null;
objB.prev = null;
或垃圾收集者会照顾我们这样的星座吗?
答案 0 :(得分:61)
任何半体面的垃圾收集器都会处理循环。
如果你进行天真的引用计数,周期只是一个问题。
大多数垃圾收集器不进行重新计数(因为它无法处理周期,因为它效率低)。相反,他们只是遵循他们可以找到的每个引用,从“根”(通常是全局和基于堆栈的变量)开始,并将他们可以找到的所有内容标记为“可达”。
然后他们只是回收所有其他记忆。
循环没有问题,因为它们只是意味着将多次到达同一节点。在第一次之后,节点将被标记为“可达”,因此GC将知道它已经存在,并跳过该节点。
基于引用计数的更原始的GC通常会实现检测和中断循环的算法。
简而言之,这不是你必须担心的事情。 我似乎记得IE6的Javascript GC实际上无法处理循环(我可能错了,自从我读它以来已经有一段时间了,而且自从我触及IE6以来已经有很长时间了),但在任何现代实现中,它都不是问题
垃圾收集器中的全部内容是抽象出内存管理。如果您必须自己完成这项工作,那么您的GC就会崩溃。
有关现代垃圾收集和使用的标记和扫描算法的更多信息,请参阅MDN。