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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7347203/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 23:48:35  来源:igfitidea点击:

Circular references in Javascript / Garbage collector

javascriptmemory-leaksgarbage-collectioncircular-reference

提问by jAndy

Can somebody explain in detail how Javascript engines deal with circular references ? Is there a big difference between browsers or even node.js ?

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

What I'm talking about is an explicit back-/next reference within objects. For instance:

我正在谈论的是对象内的显式后退/下一个引用。例如:

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

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

objA.next = objB;
objB.prev = objA;

There we go. If we do a console.log( objA )we can see that we created an infinite chain. The big question is, is this bad ? Does it create memory leaks when not explicitly cleaned?

我们走了。如果我们执行 aconsole.log( objA )我们可以看到我们创建了一个无限链。最大的问题是,这不好吗?未明确清理时是否会造成内存泄漏?

So do we have to

所以我们必须

objA.next = null;
objB.prev = null;

or will the garbage collectors take care of us on constellations like this?

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

回答by jalf

Any half-decent garbage collector will handle cycles.

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

Cycles are only a problem if you do naive reference counting.

如果您进行朴素的引用计数,循环只是一个问题。

Most garbage collectors don't do ref-counting (both because it can't handle cycles, and because it's inefficient). Instead, they simply follow every reference they can find, starting from "roots" (typically globals and stack-based variables), and mark everything they can find as "reachable".

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

Then they simply reclaim all other memory.

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

Cycles are no problem because they just mean that the same node will be reached multiple times. After the first time, the node will be marked as "reachable" already, and so the GC will know that it's been there already, and skip the node.

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

Even more primitive GC's based on reference-counting typically implement algorithms to detect and break cycles.

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

In short, it's not something you have to worry about. I seem to recall that IE6's Javascript GC actually failed to handle cycles (I could be wrong, it's been a while since I read it, and it's been much, much longer since I touched IE6), but in any modern implementation, it is no problem.

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

The entire point in a garbage collector is to abstract away memory management. If you have to do this work yourself, your GC is broken.

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

See MDNfor more information on modern garbage collection and the mark-and-sweep algorithms that are used.

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