0

Possible Duplicate:
Javascript closure?

This has probably been asked before, but...

If I want a list of functions

var funs = [
  function(){ console.log(1); },
  function(){ console.log(2); },
  function(){ console.log(3); },
  function(){ console.log(4); },
  function(){ console.log(5); } ]

it would seem that one could make it by something like:

var funs = [];
for(var i=1; i <= 5; i++){
  funs.push(function(){ console.log(i) };
}

Which doesn't work, as the variable i is a single variable bound to all the functions, so that

funs[0](); funs[1](); funs[2](); funs[3](); funs[4]();

outputs

6
6
6
6
6

not

1
2
3
4
5

This isn't the output I want. I guess I need to force javascript to bind a copy of the value of i at the time the function is created, instead of closing with the reference for i. How would I do this?

Community
  • 1
  • 1
Lucas
  • 1,869
  • 4
  • 20
  • 36

1 Answers1

3

The easiest way is passing the function through the argument of a self-executing function:

for(...) {
    (function(i) {
        // here you have a new i in every loop
    })(i);
}
ThiefMaster
  • 310,957
  • 84
  • 592
  • 636
  • Using closures works, but I just want to add that the modern way (JS >1.8.5) of doing this is by using `bind` - see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind – David Titarenco Dec 09 '12 at 18:49
  • @DavidTitarenco: You mean `push( console.log.bind(console, i) )`? Sure, that's more elegant than nesting two functions. – Bergi Dec 09 '12 at 19:02
  • You can actually do `push( console.log.bind(null, i) )` also (since you don't really care what `this` is for our purposes), but yeah. – David Titarenco Dec 09 '12 at 19:10
  • @DavidTitarenco: That will break at least in Chrome since `console` *must* be the context of `log()`. – ThiefMaster Dec 09 '12 at 19:35
  • @ThiefMaster: You're right! I was testing on Firebug. Different strokes, as they say. – David Titarenco Dec 09 '12 at 19:44