David Rodrigues
David Rodrigues

Reputation: 12532

Scope issues with for loop

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?

Upvotes: 1

Views: 57

Answers (1)

bukart
bukart

Reputation: 4906

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)

Upvotes: 2

Related Questions