I'm trying to learn Javascript closures. I'm having trouble getting my head around the fact that when you create several closures in a loop, all closures save only the last state of a variable. With this example
var links = document.getElementsByTagName('a');
for (var x=0; x<links.length; x++) attachListener();
function attachListener() {
links[x].addEventListener('click', function(){
console.log(x);
}, false);
};
When I have three links in my document, clicking on any link shows "3", I guess because x got incremented to 3 after the final run of the loop. I read in this excellent intro that if you run the outer function multiple times a new closure's created each time. So how come each closure doesn't save a different value for x each time I call the outer function?
When you pass x as a parameter to the outer function it does work as expected.
var links = document.getElementsByTagName('a');
for (x=0; x<links.length; x++) attachListener(x);
function attachListener(z) {
links[z].addEventListener('click', function(){
console.log(z);
}, false);
};
Now you get 0 when you click the first link, 1 on the second etc.
Can anyone please explain why there is this difference?
Cheers
The reason is that functions in JavaScript form closures. A closure is the combination of a function and the lexical environment within which that function was declared. This environment consists of any local variables that were in-scope at the time the closure was created.
Disadvantages of closures There are two main disadvantages of overusing closures: The variables declared inside a closure are not garbage collected. Too many closures can slow down your application. This is actually caused by duplication of code in the memory.
Difference between Function and ClosureFunction is declared using func keyword whereas Closure doesn't have func keyword. Function has always name but Closure doesn't have. Function doesn't have in keyword but closure has in the keyword.
A Closure is a combination of a function enclosed with references to its surrounding state (the lexical environment). In JavaScript, closures are created every time a function is created at run time. In other words, a closure is just a fancy name for a function that remembers the external things used inside it.
Closures do not capture the value of a variable at the time of their creation but the variable itself. A variable closed over by multiple closures is shared. This is intentional, and it is a good way of doing encapsulation in JavaScript, e.g. like this:
var makeMutablePoint = function(x, y) {
return {
position: function() {
return [x, y];
},
add: function(dx, dy) {
x = x + dx;
y = y + dy;
}
};
};
This is also the way closures work in most other languages (which is the primary reason Python is sometimes said not to have proper closures).
There is one aspect to this that is JavaScript-specific, though, which may trip you up at times (and actually seems to have done so in this case): Variables always have function scope in JavaScript. For example, in your first code snippet, there is only a single x
variable, whereas one might expect the scope of x
to be restricted to the loop body (with a new x
for each iteration). This is a quirk in the language which is probably going to be improved upon in the future by the introduction of a let
keyword with more fine-grained scoping rules.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With