2
function addHandler() { 
 var el = document.getElementById('el'); 
 el.onclick = function() { 
 this.style.backgroundColor = 'red'; 
 } 
}

The code above was included in a Mozilla blog post on JavaScript and states that the above code causes a memory leak.

Could someone explain it more than:

Because the reference to el is inadvertently caught in the closure created for the anonymous inner function. This creates a circular reference between a JavaScript object (the function) and a native object (el).

Thanks!

asked Feb 9, 2012 at 8:56

3 Answers 3

2

with my interpretation, this isn't a memoryleak per-se (sometimes you can't solve your problem without a construct like this, but they are far more complicated), but its not good, because your creating the onclick function everytime new, which keeps a 'link' to its parent (what a closure does). This code would be far better;

function clickHandler(){
 this.style.backgroundColor = 'red';
}
function addHandler() { 
 var el = document.getElementById('el'); 
 el.onclick = clickHandler 
}

this way, no closure is created, no unused references are made and no function will be generated multiple times.

answered Feb 9, 2012 at 9:01
Sign up to request clarification or add additional context in comments.

2 Comments

The answer, is then all closures when they are created keep a link to their parent. Hence the onclick closure references el which in turn references el?
in your questions code, the onclick function has a link to its parent and therefor has access to the ´el´ variable. Inside the function, the ´el´ variable is equivalent to the ´this´, hence you've got a little circle.
1

@thg435: It looks like that might be a result of using eval.

Executing the following in Firefox or Chrome with a watch on foo while breaking at debugger reports foo's value as undefined.

(function () {
 var foo = "bar";
 return function() {
 debugger;
 };
})()();

While executing the following reports foo's value as "bar" while breaking at debugger:

(function () {
 var foo = "bar";
 return function(_var) {
 debugger;
 return eval(_var);
 };
})()('foo');

It would be great to get a definitive answer on this.

answered Feb 9, 2012 at 11:10

Comments

0

The question is: does a closure capture all variables in the current scope or only those explicitly mentioned? Consider:

function makeClosure() {
 var foo = 1;
 var bar = ...some heavy object...
 return function() {
 do_something_with(foo)
 }
}

The inner function captures foo, does it capture bar as well? I guess, yes, because the following prints the correct value:

function makeClosure(bar) {
 var foo = 1;
 return function(name) {
 console.log(foo);
 console.log(eval(name));
 }
}
makeClosure('print_me')('bar')

So, in your example, el gets "inadvertently" caught in the closure (onclick handler). Thus, the closure refers to el, and el.onclick refers to the closure, qed.

answered Feb 9, 2012 at 9:41

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.