Monday, September 15, 2014

Fun with JS scope and closure : Sep 15 ATL.JS Chris Aquino

Inspired from tonights ATL.JS talk

Closure and the for loop problem:  If you really like 10
for(i=0; i < 10; i++){
setTimeout( function(){
console.log("i is " + i);}, 10);

}
Javascript is A) Lazy and B) Single Threaded.  So....  contrary to what you want:  For loop executes in the thread,  AND then the  i inside the closure function executes and sees that i now = 10 (last value).

Scope is a matter of perspective:  if you prefer undefined instead of 10
for(i=0; i < 10; i++){
setTimeout( function(i){
console.log("i is " + i);}, 10);

}
So now,  i is an argument, and it's not assigned when the function is created.  It stays undefined.

And even explicit assignment doesn't help.  The y here is part of the for loop,  so gets assigned 9 times, then function executes:
for(i=0; i < 10; i++){
var y = i;
setTimeout( function(){
console.log("i is " + y);}, 10);

}
So for readable, manageable scope: create a function to create the function, so that each execution of the loop the iterator value is captured to a isolated scope and preserved until later.

function showI(i){
function show() {
console.log("i is "+ i);
};
return show;
}

for(i=0; i < 10; i++){
setTimeout( showI(i), 10);

}

No comments:

Post a Comment