0

Possible Duplicate:
Javascript closure inside loops - simple practical example

for (i = 0; i < 100; i++) {
    setTimeout(function() {
        console.log(i);
    }, 500)
}

In the above code, it will print only 100. I know the reason. But how do i send the current i value to the callback in setTimeout?

Community
  • 1
  • 1
shahalpk
  • 3,383
  • 7
  • 36
  • 55

4 Answers4

2

Use an anonymous function inside the loop to create a closure:

for (i = 0; i < 100; i++) {

  (function(i){

    window.setTimeout(function() {
      console.log(i);
    }, 500)

  })(i);

}

As you are passing the value to the function when calling, the value will be copied and each instance of the function will have its own copy that doesn't change when the loop counter changes.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • 1
    Nit: The original callback the OP uses (`function() { console.log(i); }`) is already a closure. You are basically saying "Use a closure instead of a closure". The important point is that you are executing the function immediately, thus creating a new scope. – Felix Kling Sep 22 '12 at 19:44
  • 1
    @FelixKling: That capture captures the loop variable instead of copying it, so you need another closure, not a closure instead of the closure. – Guffa Sep 22 '12 at 19:53
  • OK, you are not saying this, but to me it sounded like this. But no, technically you don't another closure, you need a new scope (in JS a function invocation) to capture the current value of the variable. As I said, this is all nitpick, but it is not correct to refer to immediately executed functions as "closures" only. That's not the main characteristic of that construct, creating a new scope is. If JavaScript had a different syntax for closures (like PHP, as opposed to "normal" functions), the difference would be more apparent. – Felix Kling Sep 22 '12 at 22:50
1

setTimeout accepts parameters that are passed to the callback :

for (i=0;i<100;i++){
    setTimeout(function(i){
        console.log(i);
    },500, i)
}
Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
0

This works:

for (var i = 0; i < 100; i++) {
    (function(i) {
        setTimeout(function() {
            console.log(i);
        }, 500);
    })(i);
}​
David G
  • 94,763
  • 41
  • 167
  • 253
0
for (i = 0; i < 100; i++) {
    setTimeout((function(i) {
        return function(){
            console.log(i);
        }
    })(i), 500)
}
Musa
  • 96,336
  • 17
  • 118
  • 137