JavaScript DOM循环引用问题的精确解释

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript DOM循环引用问题的精确解释相关的知识,希望对你有一定的参考价值。

jQuery.data与原始expando属性(可以分配给DOM节点的任意属性)的一个被吹捧的优点是jQuery.data“不受循环引用的影响,因此没有内存泄漏”。 Google的一篇名为"Optimizing JavaScript code"的文章详细介绍:

Web应用程序最常见的内存泄漏涉及javascript脚本引擎和实现DOM的浏览器C ++对象之间的循环引用(例如,在JavaScript脚本引擎和Internet Explorer的COM基础结构之间,或者在JavaScript引擎和Firefox XPCOM基础结构之间)。

它列出了两个循环引用模式的示例:

  • DOM元素→事件处理程序→闭包范围→DOM
  • DOM元素→通过expando→中间对象→DOM元素

但是,如果DOM节点和JavaScript对象之间的引用循环产生内存泄漏,这是否意味着任何非平凡的事件处理程序(例如onclick)都会产生这样的泄漏?我不知道事件处理程序如何避免引用循环,因为我看到它的方式:

  • DOM元素引用事件处理程序。
  • 事件处理程序引用DOM(直接或间接)。在任何情况下,几乎不可能避免在任何有趣的事件处理程序中引用window,而不是编写从全局队列中读取操作的setInterval循环。

有人可以提供JavaScript↔DOM循环引用问题的精确解释吗?我想澄清的事情:

  • 什么浏览器受影响? jQuery源代码中的评论专门提到IE6-7,但谷歌文章表明Firefox也受到了影响。
  • expando属性和事件处理程序在内存泄漏方面有何不同?或者这些代码片段是否容易受到同类内存泄漏的影响? // Create an expando that references to its own element. var elem = document.getElementById('foo'); elem.myself = elem; // Create an event handler that references its own element. var elem = document.getElementById('foo'); elem.onclick = function() { elem.style.display = 'none'; };
  • 如果页面由于循环引用而泄漏内存,则泄漏是否会持续到整个浏览器应用程序关闭,或者窗口/选项卡关闭时是否释放内存?
答案

它可能不值得复制这些链接中的所有内容,所以我建议你做一些阅读,看看other Google search hits

javascript, circular references and memory leaks

Do you know what may cause memory leaks in JavaScript?

http://www.ibm.com/developerworks/web/library/wa-memleak/

http://www.ibm.com/developerworks/web/library/wa-sieve/index.html?ca=drs-

http://code.google.com/p/google-web-toolkit/wiki/UnderstandingMemoryLeaks

最糟糕的内存泄漏是在IE6中泄漏是永久性的(即使在您离开受影响的网页后)。其他泄漏通常只有在您访问该特定页面时才会在您离开页面时进行清理。

事实是浏览器应该能够处理循环引用。它应该能够看到即使DOM元素仍被JavaScript元素引用,JavaScript元素本身也只是存在,因为DOM元素仍然存在,因此没有真正的外部引用留给DOM元素。正是这种认识,IE的旧版本很糟糕。因此,在涉及事件处理程序的代码引用中,垃圾收集器需要足够聪明才能知道在JavaScript中留给DOM元素的唯一引用是当DOM元素及其事件处理程序被删除时本身会消失的引用 - 因此没有真正的外部引用,因此删除DOM元素和事件处理程序是安全的。这是一般循环引用问题的更复杂版本,所有垃圾收集器必须处理对象A引用对象B而对象B引用对象A,但没有其他对象引用A或B,因此两者都可以被释放。

jQuery的.data()使事情变得更加可靠,因为旧版本的IE在添加到DOM元素中的属性存在特殊问题,并且没有正确处理涉及这些属性中的数据的循环引用,因此在它应该具有的时候不会释放(a泄漏)。 .data()通过在DOM元素上使用一个添加的属性来解决这个问题,该元素是一个安全,无泄漏的字符串。该字符串是JavaScript对象的一个​​键,它可以包含您想要与DOM元素关联的所有属性。因为这些属性都存储在纯JavaScript中,浏览器没有循环引用错误,所以这样做不会导致泄漏。

重要的是要意识到可能仍然有一些循环引用,这没关系。解决方法是将循环引用移动到浏览器正确处理它们的位置,而不是将它们放在浏览器有bug的位置。

以上是关于JavaScript DOM循环引用问题的精确解释的主要内容,如果未能解决你的问题,请参考以下文章

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

即使有循环引用,如何将 DOM 节点序列化为 JSON?

检测 JavaScript 对象是不是有一些引用 DOM 元素的属性

数据缓存Data

数据缓存Data

是否可以缓存/归档整个 Web 文档(包括 DOM 的精确状态)并在以后重新加载?