javascript - Why isn't a variable defined in for loop not visible in setTimeout function? -


when run following code in console:

for(var k = 0; k < 36; k++){     settimeout(function(k){ alert(k)}, k*5000); } 

the alert shows undefined. moreover, expect delay of timeout function increased after every iteration; doesn't happen. timeout function should run first after 5sec after 10sec , 15sec , on.

why undefined alerted , why isn't delay increased after each iteration?

since k in local scope of timeout function, should visible inside it.

it's undefined because timer mechanism settimeout hooks function doesn't call function give arguments (by default), , you've declared k function argument. when call javascript function fewer arguments declares, value of arguments undefined. argument k shadows (hides) loop variable k, , see undefined.

to fix it, don't declare k 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, you'll have fix new problem (the 1 addressed question , answers): value of k of callbacks see same (36), because see k's value of when they're called (later, once loop over), not when they're created.

in es5 , earlier, solve this:

function createhandler(k) {     return function(){ alert(k)}; } (var k = 0; k < 36; k++){     settimeout(createhandler(k), k*5000); } 

example:

function createhandler(k) {      return function(){ console.log(k)};  }  (var k = 0; k < 36; k++){      settimeout(createhandler(k), k*500);  }

...although many create createhandler function repeatedly in 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" , above), i'd solve this:

for (let k = 0; k < 36; k++){     settimeout(() => { alert(k); }, k*5000); } 

...because when use let within for that, creates new k each iteration value doesn't change.

example:

// requires es2015+ support  (let k = 0; k < 36; k++){      settimeout(() => { console.log(k); }, k*500);  }


Comments