本文介绍了jQuery垃圾收集-这会干净吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

许多文章(例如 msdn )表示,循环引用涉及到 DOM 对象和 JS 对象.

(IE 6根本无法做到,而IE7只能在页面请求之间做到):

Javascript原生(泄漏):

function leak(){
    var elem = document.createElement("DIV");
    document.body.appendChild(elem);
    elem.onclick = function () {
        elem.innerHTML = elem.innerHTML + ".";
        // ...
    };
}

由于元素的onload属性通过闭包返回自身,因此会创建循环引用:

elem [DOM] -> elem.onclick [JS] -> elem [DOM]

JQuery版本(不泄漏):

function leak(){
    var elem = $('<div></div>');
    $(document.body).append(elem);
    elem.click(function () {
        elem.html(elem.html() + ".");
        // ...
    };
}

在这种情况下,即使仍然有循环引用,jQuery也会阻止在所有相关浏览器中发生泄漏:

elem [JS] -> element [DOM] -> elem.onclick [JS] -> elem [JS]

我的问题:如果仍然有循环引用,jQuery如何阻止泄漏?

解决方案

jQuery代码中的最后一件事(在Sizzle的代码之前,是它的选择器引擎)是(这是防止泄漏的代码):

// Prevent memory leaks in IE
// Window isn't included so as not to unbind existing unload events
// More info:
//  - http://isaacschlueter.com/2006/10/msie-memory-leaks/
if ( window.attachEvent && !window.addEventListener ) {
    window.attachEvent("onunload", function() {
        for ( var id in jQuery.cache ) {
            if ( jQuery.cache[ id ].handle ) {
                // Try/Catch is to handle iframes being unloaded, see #4280
                try {
                    jQuery.event.remove( jQuery.cache[ id ].handle.elem   );
                } catch(e) {}
            }
        }
    });
}

当您在jQuery中执行任何操作时,它既存储已完成的操作(即函数)又存储至已完成的操作(即DOM元素). onunload经过jQuery缓存,从其自己的内部缓存的事件处理程序中删除了功能(无论如何,事件处理程序是在其中存储事件的,而不是在各个DOM节点上存储的).

哦,还有一行:

if ( window.attachEvent && !window.addEventListener ) {

确保它仅在IE上运行.

Many articles (e.g. msdn) have said that a circular reference cannot be cleaned up in some browsers when it involves a DOM object and a JS object.

(IE 6 can't do it at all and IE7 can only do it between page requests):

Javascript Native (Leaks):

function leak(){
    var elem = document.createElement("DIV");
    document.body.appendChild(elem);
    elem.onclick = function () {
        elem.innerHTML = elem.innerHTML + ".";
        // ...
    };
}

Because the element's onload property refers back to itself through a closure, it creates a circular reference:

elem [DOM] -> elem.onclick [JS] -> elem [DOM]

JQuery Version (Does NOT Leak):

function leak(){
    var elem = $('<div></div>');
    $(document.body).append(elem);
    elem.click(function () {
        elem.html(elem.html() + ".");
        // ...
    };
}

In this case, jQuery stops the leak from happening in ALL browsers concerned even though there is still a circular reference:

elem [JS] -> element [DOM] -> elem.onclick [JS] -> elem [JS]

My Question: How does jQuery stop the leak if there is still a circular reference?

解决方案

The very last thing in the jQuery code (before the code for Sizzle, its selector engine) is this (which is the code to prevent the leaks):

// Prevent memory leaks in IE
// Window isn't included so as not to unbind existing unload events
// More info:
//  - http://isaacschlueter.com/2006/10/msie-memory-leaks/
if ( window.attachEvent && !window.addEventListener ) {
    window.attachEvent("onunload", function() {
        for ( var id in jQuery.cache ) {
            if ( jQuery.cache[ id ].handle ) {
                // Try/Catch is to handle iframes being unloaded, see #4280
                try {
                    jQuery.event.remove( jQuery.cache[ id ].handle.elem   );
                } catch(e) {}
            }
        }
    });
}

When you do anything in jQuery, it stores both what it has done (i.e. the function) and to what (i.e. the DOM element). onunload goes through the jQuery cache removing the functions from the event handlers of its own internal cache (which is where the events are stored anyway rather than on the individual DOM nodes).

Oh, and the line:

if ( window.attachEvent && !window.addEventListener ) {

ensures that it just runs on IE.

这篇关于jQuery垃圾收集-这会干净吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-16 19:12