问题
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