Search code examples
javascriptloopsclosuresvarlet

Loops and closures. For and Var


I found many topics explaining this problem, on how I can fix the following code by using var, like this one http://conceptf1.blogspot.com/2013/11/javascript-closures.html or this one JavaScript closure inside loops – simple practical example.

But I really can't understand why it is not working when using var and working when using let.

var funcs = [];        
for (var i = 0; i < 3; i++) {        //  let's create 3 functions
  funcs[i] = function() {            //  and store them in funcs
    console.log("My value: " + i);   //  each should log its value.
  };
}
for (var j = 0; j < 3; j++) {
  funcs[j]();                        //  and now let's run each one to see
}
// outputs 3 3 3

I really have no clue...


Solution

  • ES6's let is block scope that means it has it's own scope inside {} like many other traditional languages. But in contrast var is a global variable in your code.

    In first for loop, function is just assigned to func[i] 3 times with final value 3 but not executed. If you execute the function inside first loop, you will get the expected output though like:

    var funcs = [];
    for (var i = 0; i < 3; i++) {      // let's create 3 functions
      funcs[i] = function() {          // and store them in funcs
        console.log("My value: " + i); // each should log its value.
      };
      funcs[i](); // execution of func
    }

    So, the important thing is in which context your function is executing.

    Now, by the time funcs[j]() is executed for the first time in your code, i's value is already 3. If you want to log incremented value, you have to pass that as an argument like the following:

    var funcs = [];
    for (var i = 0; i < 3; i++) {      // let's create 3 functions
      funcs[i] = function(j) {          // and store them in funcs
        console.log("My value: " + j); // each should log its value.
      };
    }
    for (var j = 0; j < 3; j++) {
      funcs[j](j);                      // and now let's run each one to see
    }