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):
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:
ensures that it just runs on IE.