> is 'a local scope for i' the same as 'a closure' ?
No. As the article on closures
<https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/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
On Sunday, January 18, 2015 at 7:25:50 PM UTC-8, [email protected] wrote:
>
> Ah yes! Thank you serapath, I figured it out from what you said (and I
> really was being stupid!) To clarify for anyone reading:
>
> the loop kicks off the callbacks, but they don't actually get executed
> until the loop has finished. By that point i is 3, and because it is
> effectively globally scoped, this is the value that is used by *all* of the
> callbacks in the loop.
> The solution is to create a local scope for i.
>
> Thanks for the feedback guys, and sorry again for the dumb question.
>
> By the way, is 'a local scope for i' the same as 'a closure' ? I was under
> the impression these two things were not the same...?
>
>
--
Job board: http://jobs.nodejs.org/
New group rules:
https://gist.github.com/othiym23/9886289#file-moderation-policy-md
Old group rules:
https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
---
You received this message because you are subscribed to the Google Groups
"nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/nodejs/14d0e158-1722-4f2e-aef6-ef74f15cb92b%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.