问题
Possible Duplicate:
Javascript closure inside loops - simple practical example
Seen many posts talking about setTimeout and closures but I'm still not able to pass in a simple for loop counter.
for (i = 0; i < 5; i++) {
setTimeout(function () {
console.log(i);
}, Math.floor(Math.random() * 1000));
}
Gives
5
5
5
5
5
Would like to have
0
1
2
3
4
What's wrong ?
Please don't flame, I thought I have understood the setTimeout() tale but apparently not.
回答1:
You can use a closure to keep a reference to the current value of i within the loop:
for (i = 0; i < 5; i++) {
(function(i) {
setTimeout(function () {
console.log(i);
}, Math.floor(Math.random() * 1000));
})(i); //Pass current value into self-executing anonymous function
}
However, this is unlikely to print the numbers in order since you use a random timeout (you could use i * 1000 instead to make the numbers print in ascending order, one second apart).
Here's a working example.
回答2:
You need to pass i to the function being used in the setTimeout. By the time your first method is executed, i is already set to 5.
Since your timeout is variable due to the call to Math.Random(), the timeouts will be different and you won't get them in the sequence you're expecting.
Here's a working example
for (i = 0; i < 5; i++) {
(function(i) {
setTimeout(function () {
console.log(i);
}, 1000);
})(i);
}
Changing Math.floor(Math.random() * 1000) to simply 1000 ensures that the functions execute in the order you're expecting.
回答3:
You need to wrap the "interesting" code in a function that closes over i and copies it in a local variable:
for (i = 0; i < 5; i++) {
(function() {
var j = i;
setTimeout(function () {
console.log(j);
}, Math.floor(Math.random() * 1000));
})();
}
The "intermediate" function call forces the value of j to be fixed at the point that function is called, so within each setTimeout callback the value of j is different.
来源:https://stackoverflow.com/questions/10242254/settimeout-in-for-loop-with-random-delay