Javascript/垃圾收集器中的循环引用
有人可以详细解释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;
或将会照顾我们呢?
Can somebody explain in detail how Javascript engines deal with circular references ? Is there a big difference between browsers or even 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?
So do we have to
objA.next = null;
objB.prev = null;
or will the garbage collectors take care of us on constellations like this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
任何半点像样的垃圾收集器都会处理循环。
仅当您进行简单的引用计数时,循环才会成为问题。
大多数垃圾收集器不进行引用计数(既因为它无法处理循环,又因为它效率低下)。相反,他们只是从“根”(通常是全局变量和基于堆栈的变量)开始跟踪他们可以找到的每个引用,并将他们可以找到的所有内容标记为“可访问”。
然后他们简单地回收所有其他记忆。
循环没有问题,因为它们只是意味着同一个节点将被多次到达。第一次之后,该节点将被标记为“可达”,因此 GC 会知道它已经存在,并跳过该节点。
更原始的基于引用计数的 GC 通常会实现检测和中断循环的算法。
简而言之,这不是您需要担心的事情。
我似乎记得IE6的Javascript GC实际上无法处理循环(我可能是错的,自从我读它以来已经有一段时间了,自从我接触IE6以来已经很久很久了),但是在任何现代实现中,它都不是问题。
垃圾收集器的重点是抽象内存管理。如果您必须自己完成这项工作,那么您的 GC 就会损坏。
有关现代垃圾收集和标记的更多信息,请参阅 MDN使用的和扫描算法。
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.
Even more primitive GC's based on reference-counting typically implement algorithms to detect and break cycles.
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.
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.
See MDN for more information on modern garbage collection and the mark-and-sweep algorithms that are used.