Passing an array as a function argument to a setTimeout value does not mean passing a variable
The following code uses a for loop to add values to an array. Every time the current state of the array is logged to the console. The setTimeout function is then used to create a half second delay between outputs.
But the delayed output always shows the entire array with status after it has passed the whole for loop, not with status when setTimeout is called.
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);
}
How can this behavior be explained? Consider the following code, which differs in that it sends an i-variable to the callback (instead of an array):
for (var i = 0; i < 10; i++){
console.log(i);
setTimeout(function(par) { console.log(par); }, 500*i, i);
}
This snippet writes the i-variable in delayed output with its value at the time setTimeout was called. As expected, it does not register the i-variable with the value it has after the for loop.
source to share
At a half-second delay, the original pattern changes so that the hole pattern is displayed. You must clone the array for the desired effect.
Try to change
setTimeout(...);
to
(function (arr) {
setTimeout(function(par) { console.log(par); }, 500*i, arr);
})(my.slice(0));
With my.slice (0), you are cloning the entire array with the current state, so there won't be any changes to it
Update:
setTimeout(function(par) { console.log(par); }, 500, my_array.slice(0));
removed * i (you wanted half the delay) and removed the closure (unnecessary). Still works great: https://jsfiddle.net/wuL3a52x/
source to share
This is because it setTimeout
uses a reference to my
, and by the time the first callback completes, the loop has already ended.
You can use slice
to create a copy of the array every loop to make it immutable and pass it to 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());
}
source to share