Reputation:
I don't think I quite understand this concept.
I get how having stuff that require each other leads to a infinite loop but I don't see how this happens in some examples I view
function setHandler() {
var elem = document.getElementById('id')
elem.onclick = function() {
// ...
}
}
How is this a problem? I just see a element being attached a function on click.
It says there's a reference through the outer LexicalEnvironment - but isn't this occurring once?
Thanks in advance.
Upvotes: 1
Views: 61
Reputation: 338228
JavaScript uses something called lexical scoping. Scopes
function
(every time you use the keyword, a new scope is created)That means:
// +- global scope
// |
function setHandler() { // |+- scope for setHandler()
// || sees: own, global
var elem = document.getElementById('id'); // ||
// ||
elem.onclick = function() { // ||+- Scope for anonymous function
// ... // ||| sees: own, setHandler, global
} // |||
} // ||
// |
Now the anonymous function you assign to onclick
can see the variables elem
and setHandler
and everything from the global scope.
If the element is destroyed (removed from the DOM), the garbage collector considers what variables went out of scope. A less advanced garbage collector might do this by keeping a reference count for any in-memory object and clean up that object (free the memory) when the reference count reaches zero.
Now the anonymous click handler function cannot be cleaned up because it holds a reference to elem
(via the scope) which in turn holds a reference to the anonymous function (via its onclick
property). The reference count for both objects stays at 1 because the two refer to each other.
Note point 4 from above: Scopes are persistent, so the "lexical environment" of setHandler()
is kept alive even though program execution has already left that function - because it is needed by the anonymous inner function. (This is called "closure" and is one of the cornerstones of JS.)
Modern garbage collectors can spot that situation and clean up the event handler appropriately, but notably old versions if IE misbehaved and leaked the memory.
Upvotes: 0
Reputation: 147403
How is this a problem?
It was a major problem in early versions of IE 6 as it created "memory leaks" because circular references involving DOM elements led to memory not being released when a page was unloaded, so they consumed more and more memory, making the browser less responsive. There's a good article here.
In regard to the particular pattern in the OP, the circular reference is easily avoided:
function setHandler() {
var elem = document.getElementById('id')
elem.onclick = function() {
// ...
}
// Break circular reference
elem = null;
}
Upvotes: 1