110 Part I: Core Ideas
Ajax and Memory Leaks
Ajax doesn’t cause memory leaks. We need to get that out in the open right away. Misuse of
JavaScript coupled with a bad garbage collection implementation in one browser is where
the cause of this misconception truly lies. The skeptical reader may wonder why then have
you only heard of such problems since Ajax became popular? The answer is that generally
JavaScript wasn’t used enough and you didn’t stay on a page long enough to encounter the
problem. Consider that you likely may have had memory leaks in your pre-Ajax
applications but since you were posting and repainting pages fairly often, you might not
have been executing code long enough to leak too much memory. Now with Ajax, you see
the problem more often, but folks who used JavaScript for games and building Web editors
have been quite aware of JavaScript memory challenges for a number of years. So you
probably wonder: where do these memory leaks come from? There is no simple answer.
There are bugs as well as user-caused memory leaks, but in the case of Ajax you are likely
facing trouble in Internet Explorer 5, 5.5, and 6 because of event handlers and closures.
Exploring Closures
A closure is an inner function in JavaScript that becomes available outside of the enclosing
function and thus must retain variable state to act in a meaningful way. For example,
consider the following function:
function outer()
{
var x = 10;
function inner() { alert(x); }
setTimeout(inner, 1000);
}
outer();
When you run this code fragment, the function outer is invoked and has a locally
scoped function inner that will print out the variable. This inner function will be called in
1 second, but you will have left the outer function by the time the inner function is called,
so what would the value of x be? Because of the way JavaScript binds the values of the
needed variables to the function, it will actually have a value in x of 10 at the time the inner
is invoked.
This gets quite interesting if you note when these bindings actually happen. Consider
the following code, which resets the value of x.
function outer()
{
var x = 10;
function inner() { alert(x); }
setTimeout(inner, 1000);