Function in for loop behaves like a closure

I've been studying closures lately and beginning to get a hang of it, i understood from contents online and from my former question here that closures are created when a function is created inside another function (Don't know if this is the only condition for closure to exist). I decided to experiment more on this and these set of code got me confused, i didn't expect the output.

var f = [];
for(var i = 0; i < 3; i++){
  f[i] = function(){
    console.log("Number " + i);
   }
};

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

//Actual Output
//Number 0
//Number 1
//Number 2

//Expected output
//Number 3
//Number 3
//Number 3

I think i should also mention that when i replaced the second loop with Function.forEach like this

f.forEach(function(i){
  i();
});

it printed the expected output. What am i missing?

Answers


The problem is that you are redefining the i variable. With variable hoisting, your code is interpreted as:

var f = [];
var i;

for(i = 0; i < 3; i++){
  f[i] = function(){
    console.log("Number " + i);
   }
};

for(i = 0; i < 3; i++){
    // `i` is set back to 0 -> 3
    f[i]();
}

When you switch it with the forEach loop, you don't change the i variable and your closed over function works as expected.

If you want to continue to use a native for, just change var i to var j.


Need Your Help

Do FormViews not respond to commands issued from an ImageButton?

asp.net command formview linkbutton imagebutton

I am using ImageButtons in place of LinkButtons in a FormView to issue New/Edit/Delete/Cancel commands, but they don't seem to have an effect on the FormView.

How to create a standalone RESTful Service in Java to consume JSON?

java json web-services rest soap

I am trying to create a standalone RESTful Service in Java without a Web Server.