JavaScript Variable Scope [duplicate]

Solution 1:

The setTimeout callback functions are executed asynchronously, all the console.log calls you make refer to the same i variable, and at the time they are executed, the for loop has ended and i contains 4.

You could wrap your inner setTimeout call inside a function accepting a parameter in order to store a reference to all the i values that are being iterated, something like this:

setTimeout(function() {
    for (var i = 0; i < 5; i++) {
      (function (j) { // added a closure to store a reference to 'i' values
        setTimeout(function() {
            console.log(j);
        }, j * 200);
      })(i); // automatically call the function and pass the value
    }
}, 200);

Check my answer to the following question for more details:

  • Variables in Anonymous Functions — Can someone explain the following?

Solution 2:

Take a look at this question. It might help you understand the scope and closures better, very similar to your question.

Solution 3:

You're trying to create a closure containing the variable "i". But closures are only created at the end of a function. So if your functions are created in a for loop, they will all have the values from the last iteration.

You can fix it with something like this:

var createFunction = function(index) {
  return function() {
    console.log(index);
  }
};

for (var i = 0; i < 5; i++) {
  setTimeout(createFunction(i), i * 200);
}

where you return the function from another function.

Solution 4:

The variable i exists in the scope of the outer function.

It changes as the loop runs.

The inner function references it.

Try something like this:

var i_print_factory = function (value) {
  return function () {
    console.log(value);
  };
};

var init_timers = function () {
  for (var i = 0; i < 5; i++) {
    setTimeout(i_print_factory(i), i * 200);
  }
};

setTimeout(init_timers, 200);