Skip to content Skip to sidebar Skip to footer

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

Solution 1:

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 funcsconsole.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 funcsconsole.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
}

Solution 2:

Unlike to let, var is hoisted outside the loop scope. In fact, your i variable will always equals to the last iteration (which in your example is 3). let doesn’t have this problem cause it is not hoisted.

Solution 3:

Because var is function-scoped (that is, having the scope of the surrounding function), whereas let & const are block-scoped - thus having their own values inside each block (be it if- or else-block or each iteration of the loop as in your case). Block-scoped variables are not defined outside the block. Function-scoped variables stay until the end of the function.

Your i variable is function-scoped, which means once your loop is completed, it's still present outside the first loop & has a value of 3. So once you call your array function, it takes i from the upper scope (which is 3) & outputs it. If you used let, for example, you'd get a fresh binding for each iteration & your i's value would keep the initial declaration value.

Edit: So in order to output sequential values, you need to replace var with let:

for (let i = 0; i < 3; i++) {
  funcs[i] = function() {
    // now `i` is bound to the scope & keeps its initial valueconsole.log("My value: " + i); 
  };
}

Post a Comment for "Loops And Closures. For And Var"