Question

This question already has an answer here:

Consider the following Javascript code:

var a = [];

var f = function() {

    for (var i = 0; i < 3; i++) {
        a.push(function(){alert(i)});
    }
    for (var j = 0; j < 3; j++) {
        a[j]();
    }
};

The alerts print out '3' all three times. I want a different behaviour - in each iteration of the loop generate a function that prints the current value of i. I.e. 3 functions that print different indices.

Any ideas?

Was it helpful?

Solution

Create an anonymous function which accepts i as a parameter and returns that certain function:

for (var i = 0; i < 3; i++) {
    a.push((function(i) {
        return function() {
            alert(i);
        }
    })(i));
}

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

Or do something similar: create an anonymous function which accepts i as a parameter to add the function to the array:

for (var i = 0; i < 3; i++) {
    (function(i) {
        a.push(function() {
            alert(i);
        });
    })(i);
}

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

OTHER TIPS

Just another approach, using currying:

var a = [];
var f = function() {
    for (var i = 0; i < 3; i++) {
        a.push((function(a){alert(a);}).curry(i));
    }
    for (var j = 0; j < 3; j++) {
        a[j]();
    }
};

// curry implementation
Function.prototype.curry = function() {
  var fn = this, args = Array.prototype.slice.call(arguments);
  return function() {
    return fn.apply(this, args.concat(
      Array.prototype.slice.call(arguments)));
  };
};

Check the above snippet running here.

var iterate = (function () {
    var i, j = [];
    for (i = 0; i < 3; i += 1) {
        j.push(i);
        alert(j[j.length - 1]);
    }
}());

You don't need closure to merely output a value. Your code should, however, be contained in a function for object-oriented containment. Functions don't have to be called to be executed.

You can put the body of your loop in an anonymous function:

var a = [];

for(var i = 0; i < 3; i++) (function(i) {
    a.push(function() { alert(i); });
})(i)

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

By creating that function and passing the loop's value of "i" as the argument, we are creating a new "i" variable inside the body of the loop that essentially hides the outer "i". The closure you push onto the array now sees the new variable, the value of which is set when the outer function function is called in the first loop. This might be clearer if we use a different name when we create the new variable... This does the same thing:

var a = [];

for(var i = 0; i < 3; i++) (function(iNew) {
    a.push(function() { alert(iNew); });
})(i)

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

The value of "iNew" is assigned 0, then 1, then 2 because the function is called immediately by the loop.

function(i){alert(i)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top