hyl*_*aus 29 javascript closures for-loop setinterval
我正在尝试运行多个计时器,给出一个可变的项目列表.代码看起来像这样:
var list = Array(...);
for(var x in list){
setInterval(function(){
list[x] += 10;
console.log(x + "=>" + list[x] + "\n");
}, 5 * 1000);
}
Run Code Online (Sandbox Code Playgroud)
上述代码的问题在于,更新的唯一值是列表末尾的项目,乘以列表中的项目数.
任何人都可以提供解决方案和一些解释,所以我知道它为什么会这样做?
Lap*_*ple 39
var list = [1, 2, 3, 4, 5];
for (var i = 0, len = list.length; i < len; i += 1) {
(function(i) {
setInterval(function() {
list[i] += 10;
console.log(i + "=>" + list[i] + "\n");
}, 5000)
})(i);
}Run Code Online (Sandbox Code Playgroud)
这是工作代码:
var list = [1, 2, 3, 4, 5];
for (var i = 0, len = list.length; i < len; i += 1) {
(function(i) {
setInterval(function() {
list[i] += 10;
console.log(i + "=>" + list[i] + "\n");
}, 5000)
})(i);
}
Run Code Online (Sandbox Code Playgroud)
这里索引i存储在匿名函数中,因此它不会被连续循环覆盖.setInterval代码中的函数仅保留对最后一个值的引用i.
I a*_*ica 38
所以,有一些事情:
setInterval()维护对每个特定迭代期间存在x的快照值的引用,而不是快照值x.因此,正如x循环中所改变的那样,它也在每个回调函数中更新.for...in还用于枚举对象属性,并且在数组上使用时可能会出现意外行为.setTimeout()而不是setInterval().您可以通过提供其他参数来将参数传递给回调函数setTimout():
var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]);Run Code Online (Sandbox Code Playgroud)
这是一个例子:
var list = [1,2,3,4];
for (var x = 0, ln = list.length; x < ln; x++) {
setTimeout(function(y) {
console.log("%d => %d", y, list[y] += 10);
}, x * 500, x); // we're passing x
}Run Code Online (Sandbox Code Playgroud)
幸运的是,数字通过值而非参考传递.
小智 6
您可以将forEach和结合起来setTimeout以间隔遍历数组。
let modes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let interval = 1000; //one second
modes.forEach((mode, index) => {
setTimeout(() => {
console.log(mode)
}, index * interval)
})Run Code Online (Sandbox Code Playgroud)