It's undefined
because the timer mechanism setTimeout
hooks the function to doesn't call the function you give it with any arguments (by default), and you've declared k
as the function argument. When you call a JavaScript function with fewer arguments than it declares, the value of those arguments is undefined
. So the argument k
shadows (hides) the loop variable k
, and you always see undefined
.
To fix it, don't declare k
as a function argument:
for (var k = 0; k < 36; k++){
setTimeout(function(){ alert(k)}, k*5000);
// No k here -------^
}
Example (using 500 instead of 5000):
for (var k = 0; k < 36; k++){
setTimeout(function(){ console.log(k)}, k*500);
// No k here -------^
}
But, then you'll have to fix a new problem (the one addressed by this question and its answers): The value of k
that all of those callbacks see will be the same (36), because they see k
's value as of when they're called (later, once the loop is over), not when they're created.
In ES5 and earlier, I would solve that like this:
function createHandler(k) {
return function(){ alert(k)};
}
for (var k = 0; k < 36; k++){
setTimeout(createHandler(k), k*5000);
}
Example:
function createHandler(k) {
return function(){ console.log(k)};
}
for (var k = 0; k < 36; k++){
setTimeout(createHandler(k), k*500);
}
...although many would create that createHandler
function repeatedly in the loop:
for (var k = 0; k < 36; k++){
setTimeout(function(innerk) {
return function() { alert(innerk); }
}(k), k*5000);
}
Example:
for (var k = 0; k < 36; k++){
setTimeout(function(innerk) {
return function() { console.log(innerk); }
}(k), k*500);
}
In ES2015+ ("ES6" and above), I'd solve it like this:
for (let k = 0; k < 36; k++){
setTimeout(() => { alert(k); }, k*5000);
}
...because when you use let
within the for
like that, it creates a new k
for each iteration with a value that doesn't change.
Example:
// REQUIRES ES2015+ SUPPORT
for (let k = 0; k < 36; k++){
setTimeout(() => { console.log(k); }, k*500);
}