JavaScript的精确解释< - > DOM循环引用问题 [英] Precise explanation of JavaScript <-> DOM circular reference issue

查看:306
本文介绍了JavaScript的精确解释< - > DOM循环引用问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

jQuery.data 与原始expando属性(任意属性)的优势之一可以分配给DOM节点的是 jQuery.data 是安全的循环引用,因此免费从内存泄漏。来自Google的一篇名为优化JavaScript代码的文章详细介绍:

One of the touted advantages of jQuery.data versus raw expando properties (arbitrary attributes you can assign to DOM nodes) is that jQuery.data is "safe from circular references and therefore free from memory leaks". An article from Google titled "Optimizing JavaScript code" goes into more detail:


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

The most common memory leaks for web applications involve circular references between the JavaScript script engine and the browsers' C++ objects' implementing the DOM (e.g. between the JavaScript script engine and Internet Explorer's COM infrastructure, or between the JavaScript engine and Firefox XPCOM infrastructure).

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

It lists two examples of circular reference patterns:


  • DOM元素→事件处理程序→封闭范围→ DOM

  • DOM element → event handler → closure scope → DOM

DOM元素→通过expando→中介对象→ DOM元素

DOM element → via expando → intermediary object → DOM element

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

However, if a reference cycle between a DOM node and a JavaScript object produces a memory leak, doesn't this mean that any non-trivial event handler (e.g. onclick) will produce such a leak? I don't see how it's even possible for an event handler to avoid a reference cycle, because the way I see it:


  • DOM元素引用事件处理程序。

  • The DOM element references the event handler.

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

The event handler references the DOM (either directly or indirectly). In any case, it's almost impossible to avoid referencing window in any interesting event handler, short of writing a setInterval loop that reads actions from a global queue.

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

Can someone provide a precise explanation of the JavaScript ↔ DOM circular reference problem? Things I'd like clarified:


  • 影响哪些浏览器? jQuery源代码中的评论特别提及IE6-7,但谷歌文章暗示Firefox也受到影响。

  • What browsers are effected? A comment in the jQuery source specifically mentions IE6-7, but the Google article suggests Firefox is also affected.

expando属性和事件处理程序在内存方面有所不同泄漏?或者这两个代码片段是否容易受到相同类型的内存泄漏?

Are expando properties and event handlers somehow different concerning memory leaks? Or are both of these code snippets susceptible to the same kind of memory leak?

// 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';
};


  • 如果页面由于循环引用而泄漏内存,则泄漏是否会持续到整个浏览器应用程序关闭,或窗口/标签关闭时释放内存?

  • If a page leaks memory due to a circular reference, does the leak persist until the entire browser application is closed, or is the memory freed when the window/tab is closed?

    推荐答案

    可能不值得复制这些链接中的所有内容,所以我建议你做一些阅读,看看其他Google搜索点击

    It's probably not worth reproducing all the content in these links, so I'd suggest you do some reading and a look at the other Google search hits:

    javascript,循环引用和内存泄漏

    你知道什么可能导致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中,泄漏是永久性的(即使在您离开受影响的网页之后) )。其他泄漏通常只有在您访问该特定页面时才会在您离开页面时进行清理。

    The worst memory leaks are in IE6 where the leaks are permanent (even after you leave the affected web page). The other leaks are generally only while you're on that specific page and get cleaned up when you leave the page.

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

    The fact is that the browser is supposed to be able to handle circular references. It's supposed to be able to see that even though a DOM element is still being referred to by a JavaScript element, that the JavaScript element itself only exists because the DOM element is still alive and thus there is no true outside reference left to the DOM element. It is this recognition that older versions of IE were bad at. Thus in your code references that involve event handlers, the garbage collector needs to be smart enough to know that the only references left to the DOM element in JavaScript are references that themselves would go away when the DOM element and it's event handlers were removed - thus there are no true outside references so it's safe to remove both the DOM element and the event handler. This is a more complicated version of the general circular reference problem that all garbage collectors have to handle where object A refers to object B and object B refers to object A, but no other object refers to either A or B, thus both can be freed.

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

    jQuery's .data() makes things more reliable because the older versions of IE had a particular problem with properties that were added to a DOM element and did not handle circular references properly involving the data in those properties and thus would not free things when it should have (a leak). .data() works around that by only using one added property on the DOM element which is a safe, non-leaking string. That string is then a key into a JavaScript object that can contain all the properties that you would like to associate with the DOM element. Because these properties are all stored in plain JavaScript, where the browsers don't have the circular reference bugs, doing it this way doesn't cause leaks.

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

    It's important to realize that there may still be some circular references and that's OK. The work-around is to move the circular references to a place that the browsers handle them appropriately rather than putting them in the place that the browsers have bugs.

    这篇关于JavaScript的精确解释< - > DOM循环引用问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆