在JavaScript中,垃圾回收器是否会处理交叉引用的对象?

11 浏览
0 Comments

在JavaScript中,垃圾回收器是否会处理交叉引用的对象?

有人能详细解释一下JavaScript引擎如何处理循环引用吗?不同的浏览器甚至Node.js之间有很大的区别吗?\n我指的是对象内部的显式的后续/前一个引用。例如:\n

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

\n看到了吧。如果我们执行console.log( objA ),我们会发现我们创建了一个无限链。\n重要的问题是,这样做是不是不好?如果没有显式清除,会导致内存泄漏吗?\n所以我们需要这样做吗?\n

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

\n还是垃圾收集器会在这种情况下为我们处理?

0
0 Comments

在JavaScript中,垃圾回收器是否会处理交叉引用的对象?

任何一个像样的垃圾回收器都能处理循环引用。只有在做一些简单的引用计数时,循环引用才会成为一个问题。多数垃圾回收器不会使用引用计数,因为它既无法处理循环引用,也效率低下。相反,它们会从“根”开始(通常是全局变量和基于栈的变量),追踪每一个可以找到的引用,并将其标记为“可达”。然后,它们会释放所有其他内存。循环引用不是问题,因为这仅意味着相同的节点会被多次访问。在第一次访问后,该节点已被标记为“可达”,因此垃圾回收器会知道它已经被访问过,并跳过该节点。即使是基于引用计数的更为原始的垃圾回收器也通常会实现算法来检测和打破循环引用。简而言之,这不是你需要担心的问题。

我记得IE6的JavaScript垃圾回收器实际上无法处理循环引用(我可能记错了,我已经很久没有读过相关内容了,也很久没有接触IE6了),但是在任何现代实现中,这都不是问题。垃圾回收器的整个目的就是为了抽象出内存管理。如果你自己需要做这个工作,那你的垃圾回收器就是有问题的。有关现代垃圾回收和标记-清除算法的更多信息,请参阅MDN(https://developer.mozilla.org/en-US/docs/JavaScript/Memory_Management#Cycles_are_not_a_problem_anymore)。

关于google-styleguide.googlecode.com/svn/trunk/...这个链接是错误的吗?再读一遍我的回答。:)一个正常的垃圾回收器可以很好地处理循环引用。一切晚于IE6的浏览器都可以认为是正常的。如果你需要支持IE6,那么你就要担心它对循环引用的错误处理。显然,Google的指南是在假设必须支持这些有问题的浏览器的情况下编写的,所以他们必须做一些额外的工作。

在这个例子中有一些特殊情况:DOM元素是循环引用的一部分。一般来说,直到关闭页面之前,你都会泄漏内存。然而,如果我记得正确的话,IE在导航离开页面时并不总是移除对DOM的引用。(显然这样做会破坏一些页面?)Douglas Crockford也提到了这个IE6的缺陷。我认为现在我们可以认为它对大多数Web应用程序来说是不相关的。

0