-1

I am in the process of learning JavaScript. While I completely understand that JavaScript does only have function scope and not block scope, I have stumbled accross an example of a for loop in which functions are created completely and I completely ignore why the following example does not work like one would expect it to.

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
}

It outputs this:

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

And not:

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

Now I know that the solution would be something like this would be to create a function that returns a function returning the i value which would create a closure for said function.

However, my question is rather, and I have seen a couple of explanations which I don't quite get, why the example does not work in the first place and what is actually happening?

I am unsure how the array func is filled with three keys:

func[0], func[1] and func[2] while the function declaration will always return 3? Why would func[0] even exist in the first place and not only func[3]? It seems to me that there some kind of scope is created in the for loop but only for assigning a key but not for the assignment which I find odd.

Could someone enlighten me? How would a step by step evaluation of the for-loop look like and why?

Thank you very much for your help already!

Sebastian
  • 517
  • 1
  • 5
  • 12
  • The value of `i` in the function is referencing the value of `i` outside, which keeps changing. So when you finally all `func[x]`, the value of `i` is 3 (which broke the `for` loop at `i < 3`), which is shown to you. – gen_Eric May 04 '17 at 16:16
  • 2
    Also note that in ES2015 via `let` and `const` declarations JavaScript *does* have block scope. – Pointy May 04 '17 at 16:17
  • *While I completely understand that JavaScript does only have function scope and not block scope* You completely understand incorrectly. –  May 04 '17 at 16:29
  • @torazaburo: I am a newcomer to programming, so sorry if I got that wrong. Could you maybe elaborate or provide a link to help explain, please? – Sebastian May 04 '17 at 23:28
  • @RocketHazmat: Thank you! This is I guess a side effect of close which wasn't wanted here. – Sebastian May 04 '17 at 23:29
  • 1
    @RocketHazmat: This is somehow confusing as well, though, because this means JavaScript passes i as call by reference here, right? I thought JavaScript was call by value in all cases but arrays and objects? – Sebastian May 05 '17 at 06:58

1 Answers1

-1

func[0], func[1] and func[2] while the function declaration will always return 2?

No. func[i] always returns 3, because i is 3 when the function runs.

It seems to me that there some kind of scope is created in the for loop

There isn't (well, there is, but let isn't in play so it isn't used for anything). The scope is defined by the enclosing function. i exists in that scope and gets changed by the for loop.


How would a step by step evaluation of the for-loop look like and why?

var funcs = [];

Create an array

for (var i = 0; i < 3; i++) {      // let's create 3 functions

Sets i to 0, 1, 2, 3.

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

Assigns a function to the array at whatever i is currently

}

End of loop

for (var j = 0; j < 3; j++) {

Sets j to 0, 1, 2, 3.

i is still 3.

  funcs[j]();                      // and now let's run each one to see

Calls the first function. i is 3. Calls the second function. i is 3. Calls the third function. i is 3.

}

Fin.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • This is somehow confusing as well, though, because this means JavaScript passes i as call by reference here, right? I thought JavaScript was call by value in all cases but arrays and objects? – Sebastian May 05 '17 at 06:58
  • @Sebastian — It doesn't pass any variable. Your code never passes any argument at all when you call a function. – Quentin May 05 '17 at 08:15