将数组作为函数参数传递给 setTimeout 与传递变量不同
passing an array as function argument to setTimeout acts not like passing a variable
以下代码使用 for 循环将值添加到数组。每次在控制台中记录阵列的当前状态。然后使用 setTimeout 函数在输出之间创建半秒的延迟。
但是延迟输出始终显示整个数组及其通过整个 for 循环后的状态,而不是调用 setTimeout 时的状态。
var my_array = [];
for (var i = 0; i < 10; i++){
my_array[i] = "Nr " + i;
console.log(my_array);
setTimeout(function(par) { console.log(par); }, 500*i, my_array);
}
如何解释这种行为?考虑下面的代码,它是不同的,因为它将 i 变量发送到回调(而不是数组):
for (var i = 0; i < 10; i++){
console.log(i);
setTimeout(function(par) { console.log(par); }, 500*i, i);
}
此代码段将 i 变量及其调用 setTimeout 的时间值记录在延迟输出中。正如预期的那样,它不会记录 i 变量及其在 for 循环后的值。
在半秒的延迟中,原来的数组被改变,所以孔数组将被显示。您必须克隆数组以获得所需的效果
尝试更改
setTimeout(...);
到
(function (arr) {
setTimeout(function(par) { console.log(par); }, 500*i, arr);
})(my.slice(0));
使用 my.slice(0) 可以克隆具有当前状态的整个数组,因此不能对其进行任何更改
更新:
setTimeout(function(par) { console.log(par); }, 500, my_array.slice(0));
删除了 *i(你想要半秒的延迟)并删除了闭包(不必要的)。仍然完美运行:https://jsfiddle.net/wuL3a52x/
试试这个:
<script>
var my = [];
for(var i = 0; i < 10; i++)
{
my.push("Nr " + i);
var myArr=my.slice(0);
setTimeout(function(x)
{
return function()
{
console.log(x);
};
}(myArr), 1000 * i);
}
</script>
发生这种情况是因为 setTimeout
使用了对 my
的引用,并且在执行第一个回调时,循环已经结束。
您可以使用slice
在每个循环中创建数组的副本以使其不可变并将其传递给setTimeout
var my = [1,2,3,4,5,6,7,8,9,10];
for (var i = 0; i < 10; i++){
my[i] = "Nr " + i;
setTimeout(function(par) { console.log(par); }, 500*i, my.slice());
}
你可以用 async/await 解决这个问题:
function timer(ms) {
return new Promise(res => setTimeout(res, ms));
}
for (var i = 0; i < myArray.length; i++){
console.log(myArray[i]);
await timer(500);
}
以下代码使用 for 循环将值添加到数组。每次在控制台中记录阵列的当前状态。然后使用 setTimeout 函数在输出之间创建半秒的延迟。
但是延迟输出始终显示整个数组及其通过整个 for 循环后的状态,而不是调用 setTimeout 时的状态。
var my_array = [];
for (var i = 0; i < 10; i++){
my_array[i] = "Nr " + i;
console.log(my_array);
setTimeout(function(par) { console.log(par); }, 500*i, my_array);
}
如何解释这种行为?考虑下面的代码,它是不同的,因为它将 i 变量发送到回调(而不是数组):
for (var i = 0; i < 10; i++){
console.log(i);
setTimeout(function(par) { console.log(par); }, 500*i, i);
}
此代码段将 i 变量及其调用 setTimeout 的时间值记录在延迟输出中。正如预期的那样,它不会记录 i 变量及其在 for 循环后的值。
在半秒的延迟中,原来的数组被改变,所以孔数组将被显示。您必须克隆数组以获得所需的效果
尝试更改
setTimeout(...);
到
(function (arr) {
setTimeout(function(par) { console.log(par); }, 500*i, arr);
})(my.slice(0));
使用 my.slice(0) 可以克隆具有当前状态的整个数组,因此不能对其进行任何更改
更新:
setTimeout(function(par) { console.log(par); }, 500, my_array.slice(0));
删除了 *i(你想要半秒的延迟)并删除了闭包(不必要的)。仍然完美运行:https://jsfiddle.net/wuL3a52x/
试试这个:
<script>
var my = [];
for(var i = 0; i < 10; i++)
{
my.push("Nr " + i);
var myArr=my.slice(0);
setTimeout(function(x)
{
return function()
{
console.log(x);
};
}(myArr), 1000 * i);
}
</script>
发生这种情况是因为 setTimeout
使用了对 my
的引用,并且在执行第一个回调时,循环已经结束。
您可以使用slice
在每个循环中创建数组的副本以使其不可变并将其传递给setTimeout
var my = [1,2,3,4,5,6,7,8,9,10];
for (var i = 0; i < 10; i++){
my[i] = "Nr " + i;
setTimeout(function(par) { console.log(par); }, 500*i, my.slice());
}
你可以用 async/await 解决这个问题:
function timer(ms) {
return new Promise(res => setTimeout(res, ms));
}
for (var i = 0; i < myArray.length; i++){
console.log(myArray[i]);
await timer(500);
}