[Solved-5 Solutions] Javascript closure inside loops - javascript tutorial



Problem:

Code:

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

We want output like this:

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

What's the solution to this basic problem ?

Solution 1:

The problem is that the variable i, within each of your anonymous functions, is bound to the same variable outside of the function.

var funcs = [];

function createfunc(i) {
    return function() { console.log("My value: " + i); };
}

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

for (var j = 0; j < 3; j++) {
    funcs[j]();                        // and now let's run each one to see
}

Solution 2:

You can try this:

var funcs = [];

for (var i = 0; i < 3; i++) {
    funcs[i] = (function(index) {
        return function() {
            console.log("My value: " + index);
        };
    }(i));
}
for (var j = 0; j < 3; j++) {
    funcs[j]();
}

Solution 3:

You can use Function.prototype.bind

var funcs = {};
for (var i = 0; i < 3; i++) {
    funcs[i] = function(x) {
        console.log('My value: ' + x);
    }.bind(this, i);
}
for (var j = 0; j < 3; j++) {
    funcs[j]();
}

The function to be created from outside the loop and then binding the results within the loop.

function log(x) {
    console.log('My value: ' + x);
}

var funcs = [];

for (var i = 0; i < 3; i++) {
    funcs[i] = log.bind(this, i);
}

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

Solution 4:

Using an Immediately-Invoked Function Expression, the simplest way to readable and enclose an index variable:

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

    (function(index) {
        console.log('iterator: ' + index);
        //now we can also loop an ajax call here 
        //without losing track of the iterator value: $.ajax({});
    })(i);

}

Solution 5:

The scope of the variables in javascript is based on the function. In c# have a block scope, and copying the variable to one inside.

var funcs = {};
for (var i = 0; i < 3; i++) {
    let index = i;          //add this
    funcs[i] = function() {            
        console.log("My value: " + index); //change to the copy
    };
}
for (var j = 0; j < 3; j++) {
    funcs[j]();                        
}


Related Searches to Javascript closure inside loops - javascript tutorial