DOM: why is this a memory leak? DOM: why is this a memory leak? javascript javascript

DOM: why is this a memory leak?


There are two concepts that will help you understand this example.

1) Closures

The definition of a closure is that Every inner function enjoys access to its parent's function variables and parameters.

When the addHandler() function finishes, the anonymous function still has access to the parent's variable el.

2) Functions = memory

Every time you define a function a new object is created.What makes this example slightly confusing is that onclick is an event that can only be set to a DOM element once.

So surely el.onclick = function(){}; will just overwrite the old function right?

Wrong! every time addHandler runs, a new function object is created.

In conclusion:

Each time the function runs it will create a new object, with a closure containing el. Seeing as the anonymous function maintains access to el, the garbage collector cannot remove it from memory.

The anon function will maintain access to el, and el has access to the function, that is a circular reference, which causes a memory leak in IE.


Whenever you define a function in JavaScript an execution context is created for it; this execution context contains references to all the variables in the scope chain, starting from the global scope all the way up to the local scope:

function test(){    var el = document.getElementById('el');    el.onclick = function() {        // execution context of this function: el, test        alert('hello world');    }}

When test() is done, the anonymous function is not recycled yet because it's now assigned to an element of the DOM; i.e. it's being referenced by a property of the DOM element.

At the same time, the DOM element itself is also part of the function's execution context and now can't be recycled due to the cyclic reference, even though it's not immediately obvious that it's actually used; you can find a demonstration of that in this answer.

That said, nowadays, most JavaScript engines (even those found in IE) use a more advanced garbage collector that can identify unused variables a whole lot better, using techniques such as mark-and-sweep or generational / ephemeral garbage collection.

To make sure you don't run into problems on any browser (though, due to the typical lifespan of a page, this is mostly theoretical):

document.getElementById('el').onclick = function() {    alert('hello world');}


Also see the more information section of the MS article on the issue:

This memory leak occurs because DOM objects are non-JScript objects. DOM objects are not in the mark-and-sweep garbage collection scheme of JScript. Therefore, the circular reference between the DOM objects and the JScript handlers will not be broken until the browser completely tears down the page.

but note that in contrast to what is stated in that article (memory will be reclaimed when the browser goes to a new page), this article confirms that a bug in IE 6 caused the memory to be leaked forever.