1

It isn't really a problem for me. I just want to know how I can do it correctly, and not with a workaround. Well, if we use for() and some delayed events, only the last value is considered.

Test: http://jsfiddle.net/39dQV/

// Using only i (does not work)
for(var i=0; i<10; i++) {
    setTimeout(function() {
        test1.textContent = i;
    }, i * 1000);
}

// Private scope to i (does not work either)
for(var i=0; i<10; i++) {
    var x = i;

    setTimeout(function() {
        test2.textContent = x;
    }, i * 1000);
}

// Callback scope (workaround)
function set_textContent(i) {
    setTimeout(function() {
        test3.textContent = i;
    }, i * 1000);
};

for(var i=0; i<10; i++) {
    set_textContent(i);
}​

What do I need do that to so it works correctly, ie: consider the current value of i, instead of the last value changed by time?

NullUserException
  • 83,810
  • 28
  • 209
  • 234
David Rodrigues
  • 12,041
  • 16
  • 62
  • 90
  • JavaScript only establishes scope at the `function` level. Thus, your `function` approach is correct, though there are variations on the same idea. – Pointy Oct 26 '12 at 21:04
  • 1
    You want `let`, but it's basically nowhere supported. – pimvdb Oct 26 '12 at 21:05
  • Possible duplicate of [settimeout-in-a-for-loop-and-pass-i-as-value][1] [1]: http://stackoverflow.com/questions/5226285/settimeout-in-a-for-loop-and-pass-i-as-value – Johnny Oct 26 '12 at 21:06

1 Answers1

2

Your solution isn't really a "workaround", it's nearby the best way:

for(var i=0; i<10; i++) {
    setTimeout(function() {
        test1.textContent = i;
    }, i * 1000);
}

Can't work! i is in local scope an not longer defined when the function is executed.

for(var i=0; i<10; i++) {
    var x = i;

    setTimeout(function() {
        test2.textContent = x;
    }, i * 1000);
}

Same situation here, x is local in the loop.

You need a own scope for your variable. The only way to define such a scope, is to encapsulate the definition of your timeout function inside a closure or function, like you did in your third way.

I'd write it so:

for(var i=0; i<10; i++) {
    ( function( i ) {
        setTimeout(function() {
            test1.textContent = i;
        }, i * 1000);
    } ( i ) };
}

the closure defines its own scope, so the value of i is stored.

For more deeper information see: http://www.javascriptenlightenment.com/ (I love it)

bukart
  • 4,906
  • 2
  • 21
  • 40