javascript closure immediate evaluation [duplicate]

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?

Answers:

Answer

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]();
}
Answer

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.

Answer
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.

Answer

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.

Answer

function(i){alert(i)

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.