Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JQuery Garbage Collection - Will This Be Clean?

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?

like image 590
Bob Fincheimer Avatar asked Aug 03 '10 12:08

Bob Fincheimer


People also ask

What is the problem with garbage collection?

When the garbage collector runs, it can introduce delays into your application. This is because of the way GC is implemented. G1GC will pause your app while it frees unused memory objects and compacts memory regions to reduce wasted space. These GC pauses can introduce visible delays while your app is running.

Is garbage collection Necessary?

The garbage collector provides the following benefits: Frees developers from having to manually release memory. Allocates objects on the managed heap efficiently. Reclaims objects that are no longer being used, clears their memory, and keeps the memory available for future allocations.

Is garbage collection automatically in JavaScript?

Garbage collection is performed automatically. We cannot force or prevent it. Objects are retained in memory while they are reachable.

How does JavaScript handle garbage collection?

Some high-level languages, such as JavaScript, utilize a form of automatic memory management known as garbage collection (GC). The purpose of a garbage collector is to monitor memory allocation and determine when a block of allocated memory is no longer needed and reclaim it.


2 Answers

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.

like image 200
iblamefish Avatar answered Sep 21 '22 12:09

iblamefish


JQuery can only ensure there aren't leaks when you do all your manipulations through the library. There are routines in jQuery called "empty" and "cleanData" that you can peruse to see exactly what's going on, but basically the code just detaches everything it knows about from DOM elements before freeing them. That routine is called when you do something like overwrite element content with ".html()" or ".load()".

Personally I'm pretty wary of terms like "guarantee" in a situation like this.

like image 21
Pointy Avatar answered Sep 17 '22 12:09

Pointy