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

Whereas I'd like it to output:

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


The same problem occurs when the delay in running the function is caused by using event listeners:

var buttons = document.getElementsByTagName("button");
for (var i = 0; i < buttons.length; i++) {          // let's create 3 functions
  buttons[i].addEventListener("click", function() { // as event listeners
    console.log("My value: " + i);                  // each should log its value.
  });
}
<button>0</button><br>
<button>1</button><br>
<button>2</button>

What's the solution to this basic problem?

35 upvote
  flag
You sure you don't want funcs to be an array, if you're using numeric indices? Just a heads up. – DanMan
14 upvote
  flag
This is really confusing problem. This article help me in understanding it. Might it help others too. – user3199690
4 upvote
  flag
Another simple and explaned solution: 1) Nested Functions have access to the scope "above" them; 2) a closure solution... "A closure is a function having access to the parent scope, even after the parent function has closed". – Peter Krauss
2 upvote
  flag
Refer this link for better Unserstanding javascript.info/tutorial/advanced-functions – Saurabh Ahuja
13 upvote
  flag
In ES6, a trivial solution is to declare the variable i with let, which is scoped to the body of the loop. – Tomas Nikodym
1 upvote
  flag
JS functions "close over" the scope they have access to upon declaration, and retain access to that scope even as variables in that scope change. Each function in the array above closes over the global scope (global, simply because that happens to be the scope they're declared in). Later those functions are invoked logging the most current value of i in the global scope. That's JS : ) let instead of var solves this by creating a new scope each time the loop runs, creating a separated scope for each function to close over. Various other techniques do the same thing with extra functions. – Costa
1 upvote
  flag
Made a more detailed answer below: //allinonescript.com/a/41023816/1027004 – Costa
upvote
  flag
The design pattern perfectly matching this scenario //allinonescript.com/a/42512295/696535 – Pawel
upvote
  flag
why this does not work - funcs[i] = function abc () { return function() { console.log("My value: " + i); }; – MukulSharma

32 Answers 11

Try:

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

Edit (2014):

Personally I think @Aust's more recent answer about using .bind is the best way to do this kind of thing now. There's also lo-dash/underscore's _.partial when you don't need or want to mess with bind's thisArg.

up vote 1558 down vote accepted

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

What you want to do is bind the variable within each function to a separate, unchanging value 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
}

Since there is no block scope in JavaScript - only function scope - by wrapping the function creation in a new function, you ensure that the value of "i" remains as you intended.


Update: with the relatively widespread availability of the Array.prototype.forEach function (in 2015), it's worth noting that in those situations involving iteration primarily over an array of values, .forEach() provides a clean, natural way to get a distinct closure for every iteration. That is, assuming you've got some sort of array containing values (DOM references, objects, whatever), and the problem arises of setting up callbacks specific to each element, you can do this:

var someArray = [ /* whatever */ ];
// ...
someArray.forEach(function(arrayElement) {
  // ... code code code for this one element
  someAsynchronousFunction(arrayElement, function() {
    arrayElement.doSomething();
  });
});

The idea is that each invocation of the callback function used with the .forEach loop will be its own closure. The parameter passed in to that handler is the array element specific to that particular step of the iteration. If it's used in an asynchronous callback, it won't collide with any of the other callbacks established at other steps of the iteration.

If you happen to be working in jQuery, the $.each() function gives you a similar capability.

Update 2: ECMAScript 6 (ES6), the newest version of JavaScript, is now starting to be implemented in many evergreen browsers and backend systems. There are also transpilers like Babel that will convert ES6 to ES5 to allow usage of new features on older systems.

ES6 introduces new let and const keywords that are scoped differently than var-based variables. For example, in a loop with a let-based index, each iteration through the loop will have a new value of i where each value is scoped inside the loop, so your code would work as you expect. There are many resources, but I'd recommend 2ality's block-scoping post as a great source of information.

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

Beware, though, that IE9-IE11 and Edge prior to Edge 14 support let but get the above wrong (they don't create a new i each time, so all the functions above would log 3 like they would if we used var). Edge 14 finally gets it right.

1 upvote
  flag
That was a good explanation, i have been reading through closures, but not clearly understood how the i value is not unique as 1,2,3. But after reading your post, i understood that javascript does not have block scope and only have function scope. Thanks for the simple answer. – PCA
6 upvote
  flag
isn't function createfunc(i) { return function() { console.log("My value: " + i); }; } still closure because it uses the variable i? – アレックス
upvote
  flag
@Alex: Yes. All JavaScript functions create closures. The only question is the state of the closed-over variable that the function references. The solution creates a new variable scope upon invocation of createfunc that has both the i value at the time of invocation and a function that references that i. So each returned function (closure) is in its own scope closing over its own i. – cookie monster
43 upvote
  flag
Unfortunately, this answer is outdated and nobody will see the correct answer at the bottom - using Function.bind() is definitely preferable by now, see //allinonescript.com/a/19323214/785541. – Wladimir Palant
49 upvote
  flag
@Wladimir: Your suggestion that .bind() is "the correct answer" isn't right. They each have their own place. With .bind() you can't bind arguments without binding the this value. Also you get a copy of the i argument without the ability to mutate it between calls, which sometimes is needed. So they're quite different constructs, not to mention that .bind() implementations have been historically slow. Sure in the simple example either would work, but closures are an important concept to understand, and that's what the question was about. – cookie monster
upvote
  flag
@LoïcFaure-Lacroix, how let helps in capturing the values, and not references? – greenoldman
6 upvote
  flag
Please stop using these for-return function hacks, use [].forEach or [].map instead because they avoid reusing the same scope variables. – Christian Landgren
15 upvote
  flag
@ChristianLandgren: That's only useful if you're iterating an Array. These techniques aren't "hacks". They're essential knowledge. – user1106925
upvote
  flag
wow!!! this was answered in 2009 and it still works in 2015. – Nirmit Srivastava
upvote
  flag
@ChristianLandgren For instance in asynchronous callbacks, you might need to use these techniques because you don't have an array to iterate over. NirmitSrivastava Mostly what works in the early years of javascript is still compliant to whatever used today. – Carsten Farving
upvote
  flag
@CarstenFarving When dealing with asynchronous callbacks it is essential that you keep a reference to a scoped variable since the parent value may be changed between the time you create a request until you get the response. If you don't have an array, just create one with [1,2,3].forEach((i) => doSomething(i)) – Christian Landgren
upvote
  flag
This is a basic problem that 'var' variables face, i.e. they are function scoped instead of block scoped. 'var' variables undergo hoisting. This problem is overcome by 'let' statement introduced in ES6. See. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… – arnabkaycee
1 upvote
  flag
The "let" method seems to work great for me being that it does work exactly how i intended the script to work before i stumbled upon closure issues. I needed to create the function on the go restoring previous functionality to onclick behavior. In a parent function vars are set and computed and passed through. – JSG
upvote
  flag
This isn't actually that complicated. The relevant question is from @アレックス: "Isn't function createfunc(i) { return function() { console.log("My value: " + i); }; } still closure because it uses the variable i?" The answer is, Yes, of course! Now you're getting it. When a function is declared is closes over the scope in which it was declared. createFunc(i) is a whole new closure, one level deeper. Remember how functions use the nearest variable reference? What's a bit confusing is that we used i as the argument for createFunc instead of n or some other random counter. – Costa
2 upvote
  flag
Note that using let within the for loop's () doesn't work properly in IE (one workaround: add a let variable inside the {} block of the for, which does work properly in IE). – nnnnnn
upvote
  flag
Using let is best approach in new browsers, however it is more correct to add let inside for body, as @nnnnnn suggests, because for loop header has its own scope (however it works in non-IE browsers for some reason when it shouldn't). – Somnium
1 upvote
  flag
@Somnium - it's IE that implements it incorrectly. The other browsers do what the spec says. – nnnnnn
upvote
  flag
@WladimirPalant the answer you link to is a worse solution than this one. "bind" is good for setTimeout and callbacks but not for using it in a loop – Pawel
upvote
  flag
@Pawel: This question is about creating instances of a particular function bound to specific parameters - this is exactly what Function.bind() is good for. The loop merely demonstrates the principle, it's simply about binding variables that can change after the fact. In an actual loop you could use a let statement by now of course but support for it is only now becoming sufficient to be used unfortunately. – Wladimir Palant
upvote
  flag
@WladimirPalant bind primary function is to bind the context not attributes. Attributes are in addition to the context so bind in this case is an overkill. Compared to returning a function bind is 3 times slower in Chrome and 10 times slower in Firefox and Edge. – Pawel

so the reason your original example did not work is that all the closures you created in the loop referenced the same frame. in effect having 3 methods on one object with only a single 'i' variable. they all printed out the same value

What you need to understand is the scope of the variables in javascript is based on the function. This is an important difference than say c# where you have block scope, and just copying the variable to one inside the for will work.

Wrapping it in a function that evaluates returning the function like apphacker's answer will do the trick, as the variable now has the function scope.

There is also a let keyword instead of var, that would allow using the block scope rule. In that case defining a variable inside the for would do the trick. That said, the let keyword isn't a practical solution because of compatibility.

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]();                        
}
upvote
  flag
@nickf which browser? as I said, it has compatibility issues, with that I mean serious compatibility issues, like I don't think let is supported in IE. – eglasius
upvote
  flag
...nor firefox. We're talking about javascript right? – nickf
1 upvote
  flag
@nickf yes, check this reference: developer.mozilla.org/En/New_in_JavaScript_1.7 ... check the let definitions section, there is an onclick example inside a loop – eglasius
2 upvote
  flag
@nickf hmm, actually you have to explicitly specify the version: <script type="application/javascript;version=1.7"/> ... I haven't actually used it anywhere because of the IE restriction, it just isn't practical :( – eglasius
upvote
  flag
you can see browser support for the different versions here es.wikipedia.org/wiki/Javascript – eglasius
4 upvote
  flag
1 upvote
  flag
Do not use let then – regisbsb

Another way of saying it is that the i in your function is bound at the time of executing the function, not the time of creating the function.

When you create the closure, i is a reference to the variable defined in the outside scope, not a copy of it as it was when you created the closure. It will be evaluated at the time of execution.

Most of the other answers provide ways to work around by creating another variable that won't change value on you.

Just thought I'd add an explanation for clarity. For a solution, personally I'd go with Harto's since it is the most self explanatory way of doing it from the answers here. Any of the code posted will work, but I'd opt for a closure factory over having to write a pile of comments to explain why I'm declaring a new variable(Freddy and 1800's) or have weird embedded closure syntax(apphacker).

Here's another variation on the technique, similar to Bjorn's (apphacker), which lets you assign the variable value inside the function rather than passing it as a parameter, which might be clearer sometimes:

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

Note that whatever technique you use, the index variable becomes a sort of static variable, bound to the returned copy of the inner function. I.e., changes to its value are preserved between calls. It can be very handy.

upvote
  flag
Thanks and your solution works. But i would like to ask why this works, but swapping the var line and the return line wouldn't work? Thanks! – midnite
upvote
  flag
@midnite If you swapped var and return then the variable wouldn't be assigned before it returned the inner function. – Boann

This describes the common mistake with using closures in JavaScript.

A function defines a new environment

Consider:

function makeCounter()
{
  var obj = {counter: 0};
  return {
    inc: function(){obj.counter ++;},
    get: function(){return obj.counter;}
  };
}

counter1 = makeCounter();
counter2 = makeCounter();

counter1.inc();

alert(counter1.get()); // returns 1
alert(counter2.get()); // returns 0

For each time makeCounter is invoked, {counter: 0} results in a new object being created. Also, a new copy of obj is created as well to reference the new object. Thus, counter1 and counter2 are independent of each other.

Closures in loops

Using a closure in a loop is tricky.

Consider:

var counters = [];

function makeCounters(num)
{
  for (var i = 0; i < num; i++)
  {
    var obj = {counter: 0};
    counters[i] = {
      inc: function(){obj.counter++;},
      get: function(){return obj.counter;}
    }; 
  }
}

makeCounters(2);

counters[0].inc();

alert(counters[0].get()); // returns 1
alert(counters[1].get()); // returns 1

Notice that counters[0] and counters[1] are not independent. In fact, they operate on the same obj!

This is because there is only one copy of obj shared across all iterations of the loop, perhaps for performance reasons. Even though {counter: 0} creates a new object in each iteration, the same copy of obj will just get updated with a reference to the newest object.

Solution is to use another helper function:

function makeHelper(obj)
{
  return {
    inc: function(){obj.counter++;},
    get: function(){return obj.counter;}
  }; 
}

function makeCounters(num)
{
  for (var i = 0; i < num; i++)
  {
    var obj = {counter: 0};
    counters[i] = makeHelper(obj);
  }
}

This works because local variables in the function scope directly, as well as function argument variables, are allocated new copies upon entry.

For a detailed discussion, please see JavaScript closure pitfalls and usage

With ES6 now widely supported, the best answer to this question has changed. ES6 provides the let and const keywords for this exact circumstance. Instead of messing around with closures, we can just use let to set a loop scope variable like this:

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

val will then point to an object that is specific to that particular turn of the loop, and will return the correct value without the additional closure notation. This obviously significantly simplifies this problem.

const is similar to let with the additional restriction that the variable name can't be rebound to a new reference after initial assignment.

Browser support is now here for those targeting the latest versions of browsers. const/let are currently supported in the latest Firefox, Safari, Edge and Chrome. It also is supported in Node, and you can use it anywhere by taking advantage of build tools like Babel. You can see a working example here: http://jsfiddle.net/ben336/rbU4t/2/

Docs here:

Beware, though, that IE9-IE11 and Edge prior to Edge 14 support let but get the above wrong (they don't create a new i each time, so all the functions above would log 3 like they would if we used var). Edge 14 finally gets it right.

upvote
  flag
Unfortunately, 'let' is still not fully supported, especially in mobile. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… – MattC
2 upvote
  flag
As of June '16, let is supported in all major browser versions except iOS Safari, Opera Mini and Safari 9. Evergreen browsers support it. Babel will transpile it correctly to keep the expected behaviour without high compliancy mode switched on. – Dan Pantry
upvote
  flag
@DanPantry yeah about time for an update :) Updated to better reflect the current state of things, including adding a mention of const, doc links and better compatibility info. – Ben McCormick

The most simple solution would be

instead of using this

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

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

which which alters "2", for 3 times. This is because anonymous functions created in for loop, shares same closure, and in that closure, the value of i is the same. Use this to prevent shared closure,

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

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

The idea behind this is, encapsulating the entire body of the for loop with a IIFE (Immediately-Invoked Function Expression) and passing "new_i" as a parameter and capturing it as "i". Since the anonymous function is executed immediately, the "i" value is different for each function defined inside anonymous function. This solution seems to fit any such problem, since it will require minimum changes to original code suffering from this issue. In fact this is by design, it should not be an issue at all!

1 upvote
  flag
Read something similar in a book once. I prefer this, too, since you don't have to touch your existing code (as much) and it becomes obvious why you did it, once you've learned the self-calling function pattern: to trap that variable in the newly created scope. – DanMan
1 upvote
  flag
@DanMan Thanks. Self calling anonymous functions are very good way to deal javascript's lack of block level variable scope. – Kemal Dağ
3 upvote
  flag
Self-calling, or self-invoking is not the appropriate term for this technique, IIFE (Immediately-Invoked Function Expression) is more accurately. Ref: benalman.com/news/2010/11/… – jherax

try this shorter one

  • no array

  • no extra for loop


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

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

http://jsfiddle.net/7P6EN/

1 upvote
  flag
Your solution seems to output correct but it unneccessarily uses functions, why not just console.log the output? The original question is about creation of anonymous functions that has same closure. The problem was, since they have a single closure, the value of i is same for each of them. I hope you got it. – Kemal Dağ

Another way that hasn't been mentioned yet is the use of 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]();
}

jsFiddle

UPDATE

As pointed out by @squint and @mekdev, you get better performance by creating the function outside the loop first 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]();
}

jsFiddle

upvote
  flag
This is what I do these days too, I also like lo-dash/underscore's _.partial – Bjorn Tipling
14 upvote
  flag
.bind() will be largely obsolete with ECMAScript 6 features. Besides, this actually creates two functions per iteration. First the anonymous, then the one generated by .bind(). Better use would be to create it outside the loop, then .bind() it inside. – user1106925
upvote
  flag
Doesn't this trigger JsHint - Don't make functions within a loop. ? I went down this path also but after running code quality tools its a no go.. – mekdev
3 upvote
  flag
@squint @mekdev - You both are correct. My initial example was written quickly to demonstrate how bind is used. I've added another example per your suggestions. – Aust
2 upvote
  flag
I think instead of wasting computation over two O(n) loops, just do for (var i = 0; i < 3; i++) { log.call(this, i); } – user2290820
upvote
  flag
.bind() does what the accepted answer suggests PLUS fiddles with this. – niry

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

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

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

}

This sends the iterator i into the anonymous function of which we define as index. This creates a closure, where the variable i gets saved for later use in any asynchronous functionality within the IIFE.

8 upvote
  flag
For further code readability and to avoid confusion as to which i is what, I'd rename the function parameter to index. – Kyle Falconer
4 upvote
  flag
How would you use this technique to define the array funcs described in the original question? – Nico
upvote
  flag
@Nico The same way as shown in the original question, except you would use index instead of i. – JLRishe
upvote
  flag
@JLRishe var funcs = {}; for (var i = 0; i < 3; i++) { funcs[i] = (function(index) { return function() {console.log('iterator: ' + index);}; })(i); }; for (var j = 0; j < 3; j++) { funcs[j](); } – Nico
upvote
  flag
@Nico for (var i = 0; i < 3; i++) { (function(index) { funcs[index] = function () { console.log("My value: " + index); }; })(i); } – JLRishe
upvote
  flag
@JLRishe, your version is better. I think, though, that we shouldn't recommend this answer; the use of bind is simpler and more readable. – Nico
upvote
  flag
@Nico In the general case, yes .bind() is better, but when iterating over an array, .forEach() is almost always the best option. – JLRishe
1 upvote
  flag
@Nico In OP's particular case, they're just iterating over numbers, so this wouldn't be a great case for .forEach(), but a lot of the time, when one is starting off with an array, forEach() is a good choice, like: var nums [4, 6, 7]; var funcs = {}; nums.forEach(function (num, i) { funcs[i] = function () { console.log(num); }; }); – JLRishe
upvote
  flag
@Nico Actually this example solved my specific issue where I for a single value needed to make an http request and needed to keep a reference for usage in the callback and .bind nor forEach was a clean solution. – Carsten Farving

The main issue with the code shown by the OP is that i is never read until the second loop. To demonstrate, imagine seeing an error inside of the code

funcs[i] = function() {            // and store them in funcs
    throw new Error("test");
    console.log("My value: " + i); // each should log its value.
};

The error actually does not occur until funcs[someIndex] is executed (). Using this same logic, it should be apparent that the value of i is also not collected until this point either. Once the original loop finishes, i++ brings i to the value of 3 which results in the condition i < 3 failing and the loop ending. At this point, i is 3 and so when funcs[someIndex]() is used, and i is evaluated, it is 3 - every time.

To get past this, you must evaluate i as it is encountered. Note that this has already happened in the form of funcs[i] (where there are 3 unique indexes). There are several ways to capture this value. One is to pass it in as a parameter to a function which is shown in several ways already here.

Another option is to construct a function object which will be able to close over the variable. That can be accomplished thusly

jsFiddle Demo

funcs[i] = new function() {   
    var closedVariable = i;
    return function(){
        console.log("My value: " + closedVariable); 
    };
};

Here's a simple solution that uses forEach (works back to IE9):

var funcs = {};
[0,1,2].forEach(function(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
}

Prints:

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

After reading through various solutions, I'd like to add that the reason those solutions work is to rely on the concept of scope chain. It's the way JavaScript resolve a variable during execution.

  • Each function definition forms a scope consisting of all the local variables declared by var and its arguments.
  • If we have inner function defined inside another (outer) function, this forms a chain, and will be used during execution
  • When a function gets executed, the runtime evaluates variables by searching the scope chain. If a variable can be found in a certain point of the chain it will stop searching and use it, otherwise it continues until the global scope reached which belongs to window.

In the initial code:

funcs = {};
for (var i = 0; i < 3; i++) {         
  funcs[i] = function inner() {        // function inner's scope contains nothing
    console.log("My value: " + i);    
  };
}
console.log(window.i)                  // test value 'i', print 3

When funcs gets executed, the scope chain will be function inner -> global. Since the variable i cannot be found in function inner (neither declared using var nor passed as arguments), it continues to search, until the value of i is eventually found in the global scope which is window.i.

By wrapping it in an outer function either explicitly define a helper function like harto did or use an anonymous function like Bjorn did:

funcs = {};
function outer(i) {              // function outer's scope contains 'i'
  return function inner() {      // function inner, closure created
   console.log("My value: " + i);
  };
}
for (var i = 0; i < 3; i++) {
  funcs[i] = outer(i);
}
console.log(window.i)          // print 3 still

When funcs gets executed, now the scope chain will be function inner -> function outer. This time i can be found in the outer function's scope which is executed 3 times in the for loop, each time has value i bound correctly. It won't use the value of window.i when inner executed.

More detail can be found here
It includes the common mistake in creating closure in the loop as what we have here, as well as why we need closure and the performance consideration.

upvote
  flag
We rarely write this code sample in real, but I think it serves a good example to understand the fundamental. Once we have the scope in mind and how they chained together, it's more clear to see why other 'modern' ways like Array.prototype.forEach(function callback(el) {}) naturally works: The callback that's passed in naturally forms the wrapping scope with el correctly bound in each iteration of forEach. So every inner function defined in callback will be able to use the right el value – wpding

I'm surprised no one yet have suggested using the forEach function to better avoid (re)using local variables. In fact, I'm not using for(var i ...) at all anymore for this reason.

[0,2,3].forEach(function(i){ console.log('My value:', i); });
// My value: 0
// My value: 2
// My value: 3

// edited to use forEach instead of map.

3 upvote
  flag
.forEach() is a much better option if you're not actually mapping anything, and Daryl suggested that 7 months before you posted, so there's nothing to be surprised about. – JLRishe
upvote
  flag
This question is not about loop over an array – jherax
upvote
  flag
Well, he wants to create an array of functions, this example shows how to do that without involving a global variable. – Christian Landgren

Bit late to the party, but I was exploring this issue today and noticed that many of the answers don't completely address how Javascript treats scopes, which is essentially what this boils down to.

So as many others mentioned, the problem is that the inner function is referencing the same i variable. So why don't we just create a new local variable each iteration, and have the inner function reference that instead?

//overwrite console.log() so you can see the console output
console.log = function(msg) {document.body.innerHTML += '<p>' + msg + '</p>';};

var funcs = {};
for (var i = 0; i < 3; i++) {
    var ilocal = i; //create a new local variable
    funcs[i] = function() {
        console.log("My value: " + ilocal); //each should reference its own local variable
    };
}
for (var j = 0; j < 3; j++) {
    funcs[j]();
}

Just like before, where each inner function outputted the last value assigned to i, now each inner function just outputs the last value assigned to ilocal. But shouldn't each iteration have it's own ilocal?

Turns out, that's the issue. Each iteration is sharing the same scope, so every iteration after the first is just overwriting ilocal. From MDN:

Important: JavaScript does not have block scope. Variables introduced with a block are scoped to the containing function or script, and the effects of setting them persist beyond the block itself. In other words, block statements do not introduce a scope. Although "standalone" blocks are valid syntax, you do not want to use standalone blocks in JavaScript, because they don't do what you think they do, if you think they do anything like such blocks in C or Java.

Reiterated for emphasis:

JavaScript does not have block scope. Variables introduced with a block are scoped to the containing function or script

We can see this by checking ilocal before we declare it in each iteration:

//overwrite console.log() so you can see the console output
console.log = function(msg) {document.body.innerHTML += '<p>' + msg + '</p>';};

var funcs = {};
for (var i = 0; i < 3; i++) {
  console.log(ilocal);
  var ilocal = i;
}

This is exactly why this bug is so tricky. Even though you are redeclaring a variable, Javascript won't throw an error, and JSLint won't even throw a warning. This is also why the best way to solve this is to take advantage of closures, which is essentially the idea that in Javascript, inner functions have access to outer variables because inner scopes "enclose" outer scopes.

Closures

This also means that inner functions "hold onto" outer variables and keep them alive, even if the outer function returns. To utilize this, we create and call a wrapper function purely to make a new scope, declare ilocal in the new scope, and return an inner function that uses ilocal (more explanation below):

//overwrite console.log() so you can see the console output
console.log = function(msg) {document.body.innerHTML += '<p>' + msg + '</p>';};

var funcs = {};
for (var i = 0; i < 3; i++) {
    funcs[i] = (function() { //create a new scope using a wrapper function
        var ilocal = i; //capture i into a local var
        return function() { //return the inner function
            console.log("My value: " + ilocal);
        };
    })(); //remember to run the wrapper function
}
for (var j = 0; j < 3; j++) {
    funcs[j]();
}

Creating the inner function inside a wrapper function gives the inner function a private environment that only it can access, a "closure". Thus, every time we call the wrapper function we create a new inner function with it's own separate environment, ensuring that the ilocal variables don't collide and overwrite each other. A few minor optimizations gives the final answer that many other SO users gave:

//overwrite console.log() so you can see the console output
console.log = function(msg) {document.body.innerHTML += '<p>' + msg + '</p>';};

var funcs = {};
for (var i = 0; i < 3; i++) {
    funcs[i] = wrapper(i);
}
for (var j = 0; j < 3; j++) {
    funcs[j]();
}
//creates a separate environment for the inner function
function wrapper(ilocal) {
    return function() { //return the inner function
        console.log("My value: " + ilocal);
    };
}

This is a problem often encountered with asynchronous code, the variable i is mutable and at the time at which the function call is made the code using i will be executed and i will have mutated to it's last value.. thus meaning all functions created withing the loop will create a closure and i will be equal to 3 (the upper bound + 1 of the for loop.

A workaround to this, is to create a function that will hold the value of i for each iteration and force a copy i (as it is a primitive, think of it as a snapshot if it helps you).

You could use a declarative module for lists of data such as query-js(*). In these situations I personally find a declarative approach less surprising

var funcs = Query.range(0,3).each(function(i){
     return  function() {
        console.log("My value: " + i);
    };
});

You could then use your second loop and get the expected result or you could do

funcs.iterate(function(f){ f(); });

(*) I'm the author of query-js and therefor biased towards using it, so don't take my words as a recommendation for said library only for the declarative approach :)

1 upvote
  flag
I would love an explanation of the down vote. The code solves the problem at hand. It would be valuable to know how to potentially improve the code – Rune FS
1 upvote
  flag
What is Query.range(0,3)? This is not part of the tags for this question. Besides, if you use a third party library, you can provide the link of the documentation. – jherax
1 upvote
  flag
@jherax those are or course obvious improvements. Thanks for the comment. I could have sworn that there was already a link. With out that the post was pretty pointless I guess :). My initial idea of keeping it out was because I wasn't trying to push the use of my own library but more the declarative idea. However in hinsight I fully agree that the link should be there – Rune FS

I prefer to use forEach function, which has its own closure with creating a pseudo range:

var funcs = [];

new Array(3).fill(0).forEach(function (_, i) { // creating a range
    funcs[i] = function() {            
        // now i is safely incapsulated 
        console.log("My value: " + i);
    };
});

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

That looks uglier than ranges in other languages, but IMHO less monstrous than other solutions.

upvote
  flag
Prefer it to what? This seems to be a comment in reply to some other answer. It doesn't address the actual question at all (since you aren't assigning a function, to be called later, anywhere). – Quentin
upvote
  flag
Now it's clear? – Rax Wunter
upvote
  flag
It's related exactly to the mentioned issue: how to iterate safely without closure problems – Rax Wunter
upvote
  flag
Now it doesn't seem significantly different from the accepted answer. – Quentin
upvote
  flag
No. In the accepted answer it is suggested to use "some array", but we deal with a range in the answer, it's absolutely different things, which unfortunately don't have a good solution in js, so my answer is trying to solve the issue in a good and practice way – Rax Wunter
upvote
  flag
@Quentin I would recommend to investigate solution before minusing – Rax Wunter

And yet another solution: instead of creating another loop, just bind the this to the return function.

var funcs = [];

function createFunc(i) {
  return function() {
    console.log('My value: ' + i); //log value of i.
  }.call(this);
}

for (var i = 1; i <= 5; i++) {  //5 functions
  funcs[i] = createFunc(i);     // call createFunc() i=5 times
}

By binding this, solves the problem as well.

First of all, understand whats wrong with this 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
}

here when the funcs[] array is being initialized, i is being incremented, the funcs array is initialized and the size of func array becomes 3, so i = 3,. Now when the funcs[j]() is called, it is again using the variable i, which has already been incremented to 3.

Now to solve this, we have many options. Below are two of them.

  1. We can initialize i with let or initialize a new variable index with let and make it equal to i. so when the call is being made, index will be used and its scope will end after initialization. And for calling, index will be initialized again.

.

var funcs = [];
for (var i = 0; i < 3; i++) {          
    let index = i;
    funcs[i] = function() {            
        console.log("My value: " + index); 
    };
}
for (var j = 0; j < 3; j++) {
    funcs[j]();                        
}
  1. Other Option can be to introduce a tempFunc which returns the actual function.

.

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

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

You code doesn't work, because what it does is:

Create variable `funcs` and assign it an empty array;  
Loop from 0 up until it is less than 3 and assign it to variable `i`;
    Push to variable `funcs` next function:  
        // Only push (save), but don't execute
        **Write to console current value of variable `i`;**

// First loop has ended, i = 3;

Loop from 0 up until it is less than 3 and assign it to variable `j`;
    Call `j`-th function from variable `funcs`:  
        **Write to console current value of variable `i`;**  
        // Ask yourself NOW! What is the value of i?

Now the question is, what is the value of variable i when the function is called? Because first loop is created with condition i < 3, it stops immediately when the condition is false, so it is i = 3.

You need to understand that, in time when your functions are created, none of their's code is executed, it is only saved for later. And so when they are called later, the interpreter executes them and asks "what is the current value of i"?

So, your goal is to first save value of i to function and only after that save the function to funcs. This could be done for example this way:

var funcs = [];
for (var i = 0; i < 3; i++) {          // let's create 3 functions
    funcs[i] = function(x) {            // and store them in funcs
        console.log("My value: " + x); // each should log its value.
    }.bind(null, i);
}
for (var j = 0; j < 3; j++) {
    funcs[j]();                        // and now let's run each one to see
}

This way, each function will have it's own variable 'x' and we set this x to value i in each iteration.

This is only one of multiple ways how to solve this problem.

with new features of ES6 block level scoping is managed

var funcs = [];
for (let 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 (let j = 0; j < 3; j++) {
    funcs[j]();                        // and now let's run each one to see
}

code in question is replaced with let instead of var.

More on Let

Let's take advantage of new Function. Thus "i" stopes to be a varibale of a closure and becomes just a part of the text.

var funcs = [];
for (var i = 0; i < 3; i++) {
    var functionBody = 'console.log("My value: ' + i + '");';
    funcs[i] = new Function(functionBody);
}

for (var j = 0; j < 3; j++) {
    funcs[j]();
}
1 upvote
  flag
This is slow, potentially insecure, and doesn't work everywhere. – lovasoa
upvote
  flag
potentially? How? – ahitt6345

JavaScript functions "close over" the scope they have access to upon declaration, and retain access to that scope even as variables in that scope change.

var funcs = []

for (var i = 0; i < 3; i += 1) {
  funcs[i] = function () {
    console.log(i)
  }
}

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

Each function in the array above closes over the global scope (global, simply because that happens to be the scope they're declared in).

Later those functions are invoked logging the most current value of i in the global scope. That's the magic, and frustration, of closure.

"JavaScript Functions close over the scope they are declared in, and retain access to that scope even as variable values inside of that scope change."

Using let instead of var solves this by creating a new scope each time the for loop runs, creating a separated scope for each function to close over. Various other techniques do the same thing with extra functions.

var funcs = []

for (let i = 0; i < 3; i += 1) {
  funcs[i] = function () {
    console.log(i)
  }
}

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

(let makes variables that are block scoped instead of function scoped. Blocks are denoted by curly braces, but in the case of the for loop the initialization variable, i in our case, is considered to be declared in the braces.)

1 upvote
  flag
I struggled to understand this concept until I read this answer. It touches on a really important point – the value of i is being set to the global scope. When the for loop finishes running, the global value of i is now 3. Therefore, whenever that function is invoked in the array (using, say funcs[j]), the i in that function is referencing the global i variable (which is 3). – Modermo

Use closure structure, this would reduce your extra for loop. You can do it in single for loop.

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

Many solutions seem correct but they don't mention it's called Currying which is a functional programming design pattern for situations like here. 3-10 times faster than bind depending on browser.

https://www.sitepoint.com/currying-in-functional-javascript/

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

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

see performance gain in different browsers https://jsperf.com/bind-vs-curry

Maybe its too late to answer this one, but for the sake of people option I want to share my simple answer.

Another solution is, use your code as it is. Just use the variable 'i' on the second loop since all the function created pointing on the same 'i' value.

var q_v = [];

for( var i = 0; i < 3; i++ ){
    q_v[i] = function(){
        console.log('Value of i : '+ i);
    };
}

console.log( i ); // the value of i = 3

for( var i = 0; i < 3; i++ ){ // update value of i
    q_v[i](); // on every loop, it will get the new value of 'i'
}

Use ECMA-6 let keyword to bind the scope of a variable with block

var funcs = [];
for (let 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
} 

COUNTER BEING A PRIMITIVE

Lets define callback functions as follows:

// ****************************
// COUNTER BEING A PRIMITIVE
// ****************************
function test1() {
    for (var i=0; i<2; i++) {
        setTimeout(function() {
            console.log(i);
        });
    }
}
test1();
// 2
// 2

After timeout completes it will print 2 for both. This is because callback function accesses value based on lexical scope, where it was function was defined.

To pass and preserve the value while callback was defined, we can create a closure, to preserve value before the callback is invoked. This can be done as follows:

function test2() {
    function sendRequest(i) {
        setTimeout(function() {
            console.log(i);
        });
    }

    for (var i = 0; i < 2; i++) {
        sendRequest(i);
    }
}
test2();
// 1
// 2

Now whats special about this is "The primitives are passed by value and copied. Thus when the closure is defined, they keep the value from the previous loop."

COUNTER BEING AN OBJECT

Since closures have access to parent function variables via reference, this approach would differ from that for primitives.

// ****************************
// COUNTER BEING AN OBJECT
// ****************************
function test3() {
    var index = { i: 0 };
    for (index.i=0; index.i<2; index.i++) {
        setTimeout(function() {
            console.log('test3: ' + index.i);
        });
    }
}
test3();
// 2
// 2

So, even if a closure is created for the variable being passed as an object, value of loop index will not be preserved. This is to show that values on object are not copied whereas they are accessed via reference.

function test4() {
    var index = { i: 0 };
    function sendRequest(index, i) {
        setTimeout(function() {
            console.log('index: ' + index);
            console.log('i: ' + i);
            console.log(index[i]);
        });
    }

    for (index.i=0; index.i<2; index.i++) {
        sendRequest(index, index.i);
    }
}
test4();
// index: { i: 2}
// 0
// undefined

// index: { i: 2}
// 1
// undefined

Already many valid answers to this question. Not many using a functional approach though. Here is an alternative solution using the forEach method, which works well with callbacks and closures:

let arr = [1,2,3];

let myFunc = (val, index) => { console.log('val: '+val+'\nindex: '+index); };

arr.forEach(myFunc);

Not the answer you're looking for? Browse other questions tagged or ask your own question.