During an interview recently, I was asked, "What's dangerous about using closures when referencing DOM elements, like this code does?"
var firstNameValue = (function(elementId) {
var firstName = document.getElementById(elementId);
return firstName.value;
})("firstName");
Apparently, unbeknownst to me, the above code creates a memory leak in IE. The given rationale was pretty vague and I didn't understand it, but apparently this may only apply to older IE versions?
Anyone can elaborate on this?
The garbage collector used in the guts of IE to deal with memory allocated by/for the DOM has no idea how to free memory that may be dangling along allocated by the JScript engine. Thus, it just ignores such things.
So you bind an event handler to a DOM element (or something like that), and your event handler is a function created inside an invocation of some other function, and that other function has a local array with a billion things in it, well, those billion things live on and on long after the DOM element itself is junked, and even long after the page that contained it has been freed (I think; it's been a while).
function bindHandler(domElement) {
var hoHumWhatever = generateGiganticObjectNow();
domElement.onclick = function() {
alert("oww you clicked me");
};
}
Now that "hoHumWhatever" variable is maintained in the closure. When the page is reloaded or the DOM modified such that the element is thrown away, the DOM garbage collector will fail to do anything with the attribute that's pointing into JScript-owned memory. JScript, on the other hand, doesn't know that the DOM node has been freed, so it thinks the closure memory is still referenced.
I admit that this may be inaccurate in some particulars, but that's the basic problem. Various people have written about this, including Mr. Crockford and (I think) ppk at quirksmode.
edit — Upon more carefully rereading the code you posted, I think that might be an example of the similar but opposite case: the little function returns a reference to a part of a DOM value, so maybe somebody's saying that JScript will hang onto the DOM memory (instead of vice-versa). Now, in this particular case, I'm a little doubtful, because I don't see how anything "escapes" from that closure except the simple reference to the DOM attribute, which should be a primitive string instance and so which really shouldn't cause a problem. These matters can be deceptive however so I'll just sit here and scratch my head.
The following code doesn't create any closures (see below) or memory leaks.
var firstNameValue = (function(elementId) {
var firstName = document.getElementById(elementId);
return firstName.value;
})("firstName");
A bit of investigation with IE 6 shows that the code doesn't create a memory leak. I added 1,000 divs with a big slab of Lorem ipsum and unique ids, then ran 1000 anonymous functions per the above code and every time I refreshed the page it stubbornly returned to the memory use it had before I opened the page. Even adding several thousand more elements to the page to go over 100mb didn't faze it, IE kept returning to the original size.
So either this is a trick question (i.e. the correct answer is "There is no persistent closure and no circular reference so there is no memory leak") or whoever thought it up didn't write it correctly.
If it isn't a trick question, see if you can get whoever wrote it or asked the question to give you a demo of it in action.
Closure
The simple explanation of a Closure is
that ECMAScript allows inner
functions; function definitions and
function expressions that are inside
the function bodes of other functions.
And that those inner functions are
allowed access to all of the local
variables, parameters and declared
inner functions within their outer
function(s). A closure is formed when
one of those inner functions is made
accessible outside of the function in
which it was contained, so that it may
be executed after the outer function
has returned. At which point it still
has access to the local variables,
parameters and inner function
declarations of its outer function.
Those local variables, parameter and
function declarations (initially) have
the values that they had when the
outer function returned and may be
interacted with by the inner function.
Richard Cornford et al,"Javascript Closures", http://www.jibbering.com/faq/notes/closures/