3

In continuation to this question, I tried the following code that uses the same variable in both the loops and I get the desired result. My question is, WHY ?

So the initial code is:

 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]();                      // this will not give desired output
 }

The outputs this:

  • My value: 3
  • My value: 3
  • My value: 3

Whereas, the intended output is:

  • My value: 0
  • My value: 1
  • My value: 2

Now, if I use variable 'i' (a global variable) in the second loop as well, the code looks 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.
  };
}

for ( i = 0; i < 3; i++) {
  funcs[i]();                      // this gives desired output
}

I get the intended output,

  • My value: 0
  • My value: 1
  • My value: 2

WHY?

5
  • 2
    because i is a global in your code Commented Jan 29, 2017 at 11:36
  • 3 it's last value for i, when you calling it Commented Jan 29, 2017 at 11:37
  • rewrite your code to declare var i once, before the for loops - because that is what you are actually doing, the two var i are actually the same i - it becomes clear Commented Jan 29, 2017 at 11:38
  • The whole point of the "closures inside loops" issue is that the inner function prints the current value of i. If you change the second loop to e.g. for (var i = 10; i < 13; i++) { it should become more clear. Commented Jan 29, 2017 at 11:39
  • Even if you put var i it still global (at least belongs to the scope outside the fors). Try wrap each for inside a function then you'll get the result of 3 3s no matter what variable you use (even i itself). Commented Jan 29, 2017 at 11:50

2 Answers 2

2

Now, if I use variable 'i' (a global variable) in the second loop as well ... I get the intended output ... WHY?

Because when you do the first executing loop:

for (var j = 0; j < 3; j++) {
  funcs[j]();                      
 }

the loop constructing the array has finished and the global variable i has the value 3 and therefore console.log(i) results in logging 3 to the console for each iteration of the first executing loop. When you do the second executing loop:

for ( i = 0; i < 3; i++) {
  funcs[i]();                      
}

you for each iteration of the loop assign a new value to the global variable i and it is this new value that the console.log(i) will log to the console: 0, 1, 2.

How do you achieve the desired result in a simple way?

You can use let to achieve the desired result in a simple way:

"use strict"; // use of let requires strict mode

var funcs = [];

 for (let i = 0; i < 3; i++) { // just replace var with let here     
  funcs[i] = function() {          
    console.log("My value: " + i); 
  };
 }

 for (var j = 0; j < 3; j++) {
  funcs[j]();                     
 }

Now the array will be constructed with functions having access to a local variable, which is assigned the value of i at the time of adding the function to the array.

Sign up to request clarification or add additional context in comments.

Comments

1

Because the variable i is contaminated. In your snippets, The loops write to the same variable i and the functions reads it. Note that there is just one variable i in your code.

What you really need to get your intended result is called "module pattern", which wraps a function to keep a local copy of the variable in the loop:

for (var i=0; i<3; i++) {
    (function (j) {
        funcs[j] = function() {          // and store them in funcs
            console.log("My value: " + j); // each should log its value.
        };
    })(i);
}

You can read this article to get more information about "module pattern".

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.