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

Circular references in Javascript / Garbage collector

本文关键字:收集器 引用 循环 Javascript      更新时间:2023-09-26

谁能详细解释一下Javascript引擎是如何处理循环引用的?浏览器和node.js之间有很大的区别吗?

我说的是对象内显式的back/next引用。例如:

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;

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

任何像样的垃圾收集器都可以处理循环。

循环只有在进行朴素引用计数时才会出现问题。

大多数垃圾收集器不进行refcount(因为它不能处理循环,而且效率低下)。相反,它们只是遵循它们能找到的每个引用,从"根"(通常是全局变量和基于堆栈的变量)开始,并将它们能找到的所有引用标记为"可达"。

然后它们简单地回收所有其他内存。

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

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

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

垃圾收集器的全部意义在于抽象内存管理。如果你必须自己做这些工作,你的GC就坏了。

请参阅MDN以获取有关现代垃圾收集和所使用的标记-清除算法的更多信息。