No. As
the article on closures that Adrien linked to states, a closure is a function that refers to variables in the environment in which it is created.
So a closure in a loop looks like this:
for (var i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
The inner function is called a closure because it refers to the variable "i", which is defined in the outer environment. The important thing to remember is that when the closure, the inner function, is created, it isn't binding to the current value of "i", but rather to the variable. The current value may be different if the function is executed later, as it is in this example, which will execute the 10 instances of the inner function after 1 second and all of them will see "i" as having a value of 10 because that's the state the loop left "i" in after it finished looping a second earlier.
But if you do something like this:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].forEach(function(i) {
setTimeout(function() {
console.log(i);
});
});
Note that there are two functions being created. The inner function is a closure because it refers to "i" which is coming from its environment, but the outer function is not a closure because the variable "i" is not defined in the outside environment, it is defined inside the function (in the arguments list). This is the function that gives "i" a local scope. Note that variables defined in the arguments list are treated the same as variables defined with "var" statements within the function -- they "belong" to that function, their scope is the function.
If you still want to use "for" instead of Array.forEach() (or if you want to use "for...in" instead of Object.keys()) then you can explicitly bind the current value of "i" to the inner function via Function.bind() and it will be passed into the function as an argument when the function is executed. This is called "currying". It isn't the primary function of bind (the primary function is binding the "this" value, but since we don't care about that, we pass "null" as the first argument to bind()):
for (var i = 0; i < 10; i++) {
setTimeout(function(j) {
console.log(j);
}.bind(null, i), 1000);
}
We could have named the argument "i" as well, since this variable is scoped to the inner function, it will take precedence over the "i" in the outer function and would make the "i" in the outer function inaccessible. This function is not a closure because it isn't referring to a variable in the outside environment (but Function.bind() isn't magic, it probably uses a closure internally).
-- Peter Rust
Cornerstone Systems