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

标签 javascript memory-leaks garbage-collection circular-reference

有人可以详细解释 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;

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

最佳答案

任何半正经的垃圾收集器都会处理循环。

只有在您进行简单的引用计数时,循环才会成为问题。

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

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

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

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

简而言之,这不是您必须担心的事情。 我似乎记得 IE6 的 Javascript GC 实际上无法处理循环(我可能是错的,我读它已经有一段时间了,而且我接触 IE6 已经很久很久了),但在任何现代实现中,它都不是问题。

垃圾收集器的全部意义在于抽象出内存管理。如果您必须自己完成这项工作,那么您的 GC 就坏了。

参见 MDN有关现代垃圾收集和所使用的标记清除算法的更多信息。

关于javascript - Javascript/垃圾收集器中的循环引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17360683/

相关文章:

javascript - 提交表单后显示一个div并保留表单的信息

javascript - 为什么 async await 和 Promise.all 的运行时间相同?

C++ - std::list remove_if 不释放内存?

java - Java VM 是否移动内存中的对象,如果是,如何移动?

java - 这是正常的内存行为吗?

javascript - Node.js:监听器有问题

构造函数中的 C++ 单例

c++ - valgrind 检测到堆栈粉碎

java - GC 日志旋转数据在应用程序重启时丢失

javascript - 索引 :145 Uncaught TypeError: map. mapTypes.insertAt 不是函数