Reputation: 12670
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!
Upvotes: 2
Views: 191
Reputation: 6516
@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.
Upvotes: 1
Reputation: 214959
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.
Upvotes: 0
Reputation: 5025
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.
Upvotes: 2