For Loop in Javascript, only value from last iteration is output

I have this Javascript code that 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> 

First it shows "test1", and then "test2" after a second, as such: "test1test2", which is what I want.

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

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

Then I first get "test2" and then "test2" after a second, as such: "test2test2", which I don't want.

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

+4
source share
5 answers

var i incremented to 2 when setTimeout executes the function and therefore just prints the value of i as 2, which results in test2test2 .

You must use closure to use instance 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: function arguments used.

+5
source

The for loop does not create a new scope, you can use another function for this:

 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; } 
+3
source

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

How JavaScript scope works.

See answer from @Esailija for solution.

+2
source

This is because you are not committing the value of i from the for loop. You can configure your code for this to 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; } 
0
source

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

  • Use $.each instead of the for loop, so you have access to the i variable in any scope.

  • Use delay instead of setTimeout . To do this, you first need to start the queue: $(".test").show(0).delay(timeInterval).append("test" + i)

0
source

Source: https://habr.com/ru/post/1442194/


All Articles