October 21, 2005
From Quirksmode:
Since these two last scripts are in line with common ways of setting event handlers, while the leaking scripts are very odd and non-real-life, I don't see the problem with event handling. As long as you use simple, common ways of setting event handlers, what can go wrong?
PPK posted the following example (test page) which doesn't leak:
// DOESN'T LEAK
window.onload = init;
function init()
{
createLinks();
var x = document.getElementsByTagName('a');
for (var i=0;i<x.length;i++)
{
x[i].onclick = function () {
this.firstChild.nodeValue = ' Clicked! - ';
}
}
}
However, a small change will also make it leak.
In this real life scenario we now keep a reference to el to set the
className as well.
// LEAK
window.onload = init;
function init()
{
createLinks();
var x = document.getElementsByTagName('a');
for (var i=0;i<x.length;i++)
{
var el = x[i];
el.onclick = function () {
this.firstChild.nodeValue = ' Clicked! - ';
};
el.className = "someClass";
}
}
This is caused by the reference to el in the
scope of the eventhandler. And since this is run in a loop,
only x[x.length - 1] is leaked. To make this
leak visible, I added a large string to it (test page).
With help of my closure function we can rewrite this to:
// DOESN'T LEAK
window.onload = init;
function init()
{
createLinks();
var x = document.getElementsByTagName('a');
for (var i=0;i<x.length;i++)
{
var el = x[i];
el.onclick = function () {
this.firstChild.nodeValue = ' Clicked! - ';
}.closure(el);
el.className = "someClass";
}
}
Which doesn't leak (test page).