4

I have this Javascript code, which works as expected:

<div class="test"></div>

<script>
setTimeout(function(){$(".test").append("test1")},1000);
setTimeout(function(){$(".test").append("test2")},2000);
</script>
<script src="js/jquery.min.js"></script>

It shows "test1" first and then "test2" a second later, as such: "test1test2", which is what I want.

When I try to do this in a FOR loop, like this:

var timeInterval = 1000;
for (var i = 0, l = 2; i < l; i++ ) {
    setTimeout(function(){$(".test").append("test" + i)},timeInterval);
    timeInterval += 1000;
}

Then I get "test2" first and then "test2" a second later, as such: "test2test2", which is not what I want.

In fact, if l = 3, then I get "test3test3test3" instead of "test1test2test3". Does anybody know how to solve this problem?

1
  • I think because the timeout is longer then the speed it is going through i, so by the time it evaluates i it is already at 3 Commented Oct 25, 2012 at 21:51

5 Answers 5

5

The var i is incremented to 2 when the setTimeout is executing the function and so it just prints the i value as 2 resulting in test2test2.

You should use a closure to use the instance of i which will print test1test.

DEMO: http://jsfiddle.net/mBBJn/1/

var timeInterval = 1000;
for (var i = 0, l = 2; i < l; i++) {
    (function(i) {
        setTimeout(function() {
            $(".test").append("test" + (i+1))
        }, timeInterval);
        timeInterval += 1000;
    })(i);
}

Edit: used function args.

Sign up to request clarification or add additional context in comments.

Comments

3

The for loop doesn't create a new scope, you can use another function to do it:

var timeInterval = 1000;
for (var i = 0, l = 2; i < l; i++) {
    setTimeout((function(i) {
        return function() {
            $(".test").append("test" + i);
        }
    })(i), timeInterval);
    timeInterval += 1000;
}

Comments

2

The variable i will always refer to the current value of i (not the value of i when called) in this situation.

That's how scope works in JavaScript.

See the answer by @Esailija for a solution.

Comments

0

The most obvious way to keep i in scope is solved in other answers, but since you're using jQuery you have other options.

  1. Use $.each instead of for loop, that way you have access to i variable anywhere in that scope.

  2. Use delay instead of setTimeout. For this to work you need to trigger a queue first: $(".test").show(0).delay(timeInterval).append("test" + i)

Comments

0

This is because you aren't capturing the value of i from the for-loop. You can tweak your code to this to make it work:

var timeInterval = 1000;
for (var i = 0, l = 2; i < l; i++ ) {
    (function(i2, timeInterval2) {
        setTimeout(function() {
            $(".test").append("test" + i2);
        }, timeInterval2);
    })(i, timeInterval);
    timeInterval += 1000;
}

1 Comment

Thanks Cory for your suggestion. You need to remove one of the close brackets from: timeInterval)); to timeInterval); and it works.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.