JavaScript closure inside loops – simple practical example












2462

















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>





… or asynchronous code, e.g. using Promises:






// Some async wait function
const wait = (ms) => new Promise((resolve, reject) => setTimeout(resolve, ms));

for(var i = 0; i < 3; i++){
wait(i * 100).then(() => console.log(i)); // Log `i` as soon as each promise resolves.
}





What’s the solution to this basic problem?










share|improve this question























  • 48




    You sure you don't want funcs to be an array, if you're using numeric indices? Just a heads up.
    – DanMan
    Jul 26 '13 at 11:12






  • 21




    This is really confusing problem. This article help me in understanding it. Might it help others too.
    – user3199690
    May 3 '14 at 15:38






  • 4




    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
    Dec 17 '14 at 1:22








  • 2




    Refer this link for better Unserstanding javascript.info/tutorial/advanced-functions
    – Saurabh Ahuja
    Apr 2 '15 at 12:01








  • 22




    In ES6, a trivial solution is to declare the variable i with let, which is scoped to the body of the loop.
    – Tomas Nikodym
    Sep 13 '16 at 20:34
















2462

















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>





… or asynchronous code, e.g. using Promises:






// Some async wait function
const wait = (ms) => new Promise((resolve, reject) => setTimeout(resolve, ms));

for(var i = 0; i < 3; i++){
wait(i * 100).then(() => console.log(i)); // Log `i` as soon as each promise resolves.
}





What’s the solution to this basic problem?










share|improve this question























  • 48




    You sure you don't want funcs to be an array, if you're using numeric indices? Just a heads up.
    – DanMan
    Jul 26 '13 at 11:12






  • 21




    This is really confusing problem. This article help me in understanding it. Might it help others too.
    – user3199690
    May 3 '14 at 15:38






  • 4




    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
    Dec 17 '14 at 1:22








  • 2




    Refer this link for better Unserstanding javascript.info/tutorial/advanced-functions
    – Saurabh Ahuja
    Apr 2 '15 at 12:01








  • 22




    In ES6, a trivial solution is to declare the variable i with let, which is scoped to the body of the loop.
    – Tomas Nikodym
    Sep 13 '16 at 20:34














2462












2462








2462


893








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>





… or asynchronous code, e.g. using Promises:






// Some async wait function
const wait = (ms) => new Promise((resolve, reject) => setTimeout(resolve, ms));

for(var i = 0; i < 3; i++){
wait(i * 100).then(() => console.log(i)); // Log `i` as soon as each promise resolves.
}





What’s the solution to this basic problem?










share|improve this question


















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>





… or asynchronous code, e.g. using Promises:






// Some async wait function
const wait = (ms) => new Promise((resolve, reject) => setTimeout(resolve, ms));

for(var i = 0; i < 3; i++){
wait(i * 100).then(() => console.log(i)); // Log `i` as soon as each promise resolves.
}





What’s the solution to this basic problem?






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
}





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
}





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>





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>





// Some async wait function
const wait = (ms) => new Promise((resolve, reject) => setTimeout(resolve, ms));

for(var i = 0; i < 3; i++){
wait(i * 100).then(() => console.log(i)); // Log `i` as soon as each promise resolves.
}





// Some async wait function
const wait = (ms) => new Promise((resolve, reject) => setTimeout(resolve, ms));

for(var i = 0; i < 3; i++){
wait(i * 100).then(() => console.log(i)); // Log `i` as soon as each promise resolves.
}






javascript loops closures






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jun 22 at 19:02









Xufox

9,94562848




9,94562848










asked Apr 15 '09 at 6:06









nickf

369k171581687




369k171581687












  • 48




    You sure you don't want funcs to be an array, if you're using numeric indices? Just a heads up.
    – DanMan
    Jul 26 '13 at 11:12






  • 21




    This is really confusing problem. This article help me in understanding it. Might it help others too.
    – user3199690
    May 3 '14 at 15:38






  • 4




    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
    Dec 17 '14 at 1:22








  • 2




    Refer this link for better Unserstanding javascript.info/tutorial/advanced-functions
    – Saurabh Ahuja
    Apr 2 '15 at 12:01








  • 22




    In ES6, a trivial solution is to declare the variable i with let, which is scoped to the body of the loop.
    – Tomas Nikodym
    Sep 13 '16 at 20:34














  • 48




    You sure you don't want funcs to be an array, if you're using numeric indices? Just a heads up.
    – DanMan
    Jul 26 '13 at 11:12






  • 21




    This is really confusing problem. This article help me in understanding it. Might it help others too.
    – user3199690
    May 3 '14 at 15:38






  • 4




    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
    Dec 17 '14 at 1:22








  • 2




    Refer this link for better Unserstanding javascript.info/tutorial/advanced-functions
    – Saurabh Ahuja
    Apr 2 '15 at 12:01








  • 22




    In ES6, a trivial solution is to declare the variable i with let, which is scoped to the body of the loop.
    – Tomas Nikodym
    Sep 13 '16 at 20:34








48




48




You sure you don't want funcs to be an array, if you're using numeric indices? Just a heads up.
– DanMan
Jul 26 '13 at 11:12




You sure you don't want funcs to be an array, if you're using numeric indices? Just a heads up.
– DanMan
Jul 26 '13 at 11:12




21




21




This is really confusing problem. This article help me in understanding it. Might it help others too.
– user3199690
May 3 '14 at 15:38




This is really confusing problem. This article help me in understanding it. Might it help others too.
– user3199690
May 3 '14 at 15:38




4




4




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
Dec 17 '14 at 1:22






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
Dec 17 '14 at 1:22






2




2




Refer this link for better Unserstanding javascript.info/tutorial/advanced-functions
– Saurabh Ahuja
Apr 2 '15 at 12:01






Refer this link for better Unserstanding javascript.info/tutorial/advanced-functions
– Saurabh Ahuja
Apr 2 '15 at 12:01






22




22




In ES6, a trivial solution is to declare the variable i with let, which is scoped to the body of the loop.
– Tomas Nikodym
Sep 13 '16 at 20:34




In ES6, a trivial solution is to declare the variable i with let, which is scoped to the body of the loop.
– Tomas Nikodym
Sep 13 '16 at 20:34












39 Answers
39






active

oldest

votes













1 2
next












1892














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



Classic solution: Closures



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.





2015 Solution: forEach



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.





ES6 solution: let



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.






share|improve this answer



















  • 7




    isn't function createfunc(i) { return function() { console.log("My value: " + i); }; } still closure because it uses the variable i?
    – アレックス
    Mar 28 '14 at 3:45






  • 48




    Unfortunately, this answer is outdated and nobody will see the correct answer at the bottom - using Function.bind() is definitely preferable by now, see stackoverflow.com/a/19323214/785541.
    – Wladimir Palant
    Jun 20 '14 at 12:21






  • 67




    @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
    Jul 12 '14 at 2:35






  • 7




    Please stop using these for-return function hacks, use .forEach or .map instead because they avoid reusing the same scope variables.
    – Christian Landgren
    Feb 7 '15 at 10:23






  • 23




    @ChristianLandgren: That's only useful if you're iterating an Array. These techniques aren't "hacks". They're essential knowledge.
    – user1106925
    Jun 29 '15 at 16:31



















349














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.






share|improve this answer























  • any explanation about the }(i)); ?
    – aswzen
    Apr 6 at 1:32






  • 3




    @aswzen I think it passes i as the argument index to the function.
    – Jet Blue
    Jul 26 at 22:01



















320














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





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








share|improve this answer























  • This is what I do these days too, I also like lo-dash/underscore's _.partial
    – Bjorn Tipling
    Dec 8 '14 at 5:18






  • 16




    .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
    Jun 28 '15 at 3:29










  • 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
    Jun 28 '15 at 18:32






  • 4




    @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
    Jun 29 '15 at 16:23






  • 4




    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
    Sep 11 '15 at 12:14





















243














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.






share|improve this answer



















  • 8




    For further code readability and to avoid confusion as to which i is what, I'd rename the function parameter to index.
    – Kyle Falconer
    Jan 10 '14 at 16:45






  • 4




    How would you use this technique to define the array funcs described in the original question?
    – Nico
    Nov 30 '14 at 13:17










  • @Nico The same way as shown in the original question, except you would use index instead of i.
    – JLRishe
    Mar 31 '15 at 20:54










  • @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
    Apr 1 '15 at 9:22








  • 1




    @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
    Apr 1 '15 at 10:05





















137














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





Update



With ES6 now mainstream, we can now use the new let keyword to create block-scoped variables:






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

var funcs = {};
for (let i = 0; i < 3; i++) { // use "let" to declare "i"
funcs[i] = function() {
console.log("My value: " + i); //each should reference its own local variable
};
}
for (var j = 0; j < 3; j++) { // we can use "var" here without issue
funcs[j]();
}





Look how easy it is now! For more information see this answer, which my info is based off of.






share|improve this answer























  • I like how you explained the IIFE way as well. I was looking for that. Thank you.
    – CapturedTree
    Oct 26 '17 at 21:45






  • 3




    There is now such a thing as block scoping in JavaScript using the let and const keywords. If this answer were to expand to include that, it would be much more globally useful in my opinion.
    – Tiny Giant
    Dec 27 '17 at 3:12










  • @TinyGiant sure thing, I added some info about let and linked a more complete explanation
    – woojoo666
    Mar 1 at 22:44










  • @woojoo666 Could your answer also work for calling two alternating URL's in a loop like so: i=0; while(i < 100) { setTimeout(function(){ window.open("https://www.bbc.com","_self") }, 3000); setTimeout(function(){ window.open("https://www.cnn.com","_self") }, 3000); i++ }? (could replace window.open() with getelementbyid......)
    – nutty about natty
    May 14 at 19:08












  • @nuttyaboutnatty sorry about such a late reply. It doesn't seem like the code in your example already works. You aren't using i in your timeout functions, so you don't need a closure
    – woojoo666
    Jun 3 at 22:58



















128














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:




  • const

  • let


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.






share|improve this answer























  • Unfortunately, 'let' is still not fully supported, especially in mobile. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
    – MattC
    Feb 23 '16 at 17:47






  • 2




    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
    Jun 22 '16 at 10:18












  • @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
    Jun 27 '16 at 14:24












  • Isn't this why we use babel to transpile our code so browsers that don't support ES6/7 can understand what's going on?
    – pixel 67
    Mar 19 at 15:56



















79














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 the value for 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).






share|improve this answer































    62














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





    share|improve this answer























    • @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
      Apr 15 '09 at 6:54






    • 1




      @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
      Apr 16 '09 at 2:55






    • 2




      @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
      Apr 16 '09 at 2:58






    • 4




      See also What browsers currently support javascript's 'let' keyword?
      – rds
      Jan 15 '13 at 10:21






    • 1




      Do not use let then
      – regisbsb
      Oct 14 '13 at 17:13



















    50














    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.






    share|improve this answer





















    • 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
      Dec 3 '13 at 2:56










    • @midnite If you swapped var and return then the variable wouldn't be assigned before it returned the inner function.
      – Boann
      Dec 3 '13 at 4:35





















    46














    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






    share|improve this answer





























      42














      The most simple solution would be,



      Instead of using:



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

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


      which alerts "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 an 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 the anonymous function.



      This solution seems to fit any such problem since it will require minimal changes to the original code suffering from this issue. In fact, this is by design, it should not be an issue at all!






      share|improve this answer



















      • 2




        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
        Jul 26 '13 at 11:18








      • 1




        @DanMan Thanks. Self calling anonymous functions are very good way to deal javascript's lack of block level variable scope.
        – Kemal Dağ
        Jul 26 '13 at 12:20








      • 3




        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
        Oct 27 '15 at 4:29



















      25














      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/






      share|improve this answer

















      • 1




        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ğ
        Jun 28 '15 at 8:51



















      21














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





      share|improve this answer





























        21














        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






        share|improve this answer























        • forEach does not support IE8 or lower version !!!
          – Bimal Das
          Jan 16 at 13:16










        • That's why I said "works back to IE9" ....
          – Daryl
          Jan 17 at 23:38



















        17














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






        share|improve this answer



















        • 1




          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
          Apr 5 '17 at 2:50



















        12














        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.






        share|improve this answer























        • 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
          Apr 26 '17 at 14:19



















        11














        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
        }


        The code in OP's question is replaced with let instead of var.






        share|improve this answer























        • const provides the same result, and should be used when the value of a variable will not change. However, the use of const inside the initializer of the for loop is implemented incorrectly in Firefox and has yet to be fixed. Instead of being declared inside the block, it is declared outside the block, which results in a redeclaration to the variable, which in turn results in an error. The use of let inside the initializer is implemented correctly in Firefox, so no need to worry there.
          – Tiny Giant
          Dec 27 '17 at 3:05



















        7














        I'm surprised no one yet has 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.






        share|improve this answer



















        • 3




          .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
          Mar 31 '15 at 19:59












        • This question is not about loop over an array
          – jherax
          Oct 27 '15 at 4:14










        • Well, he wants to create an array of functions, this example shows how to do that without involving a global variable.
          – Christian Landgren
          Nov 11 '15 at 21:25



















        6














        First of all, understand what's 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]();
          }



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







        share|improve this answer































          6














          This question really shows the history of JavaScript! Now we can avoid block scoping with arrow functions and handle loops directly from DOM nodes using Object methods.






          const funcs = [1, 2, 3].map(i => () => console.log(i));
          funcs.map(fn => fn())








          const buttons = document.getElementsByTagName("button");
          Object
          .keys(buttons)
          .map(i => buttons[i].addEventListener('click', () => console.log(i)));

          <button>0</button><br>
          <button>1</button><br>
          <button>2</button>








          share|improve this answer





























            6















            We will check , what actually happens when you declare var and let
            one by one.





            Case1 : using var



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


            Now open your chrome console window by pressing F12 and refresh the page.
            Expend every 3 functions inside the array.You will see an property called [[Scopes]].Expand that one. You will see one
            array object called "Global",expand that one. You will find a property 'i' declared into the object which having value 3.



            enter image description here



            enter image description here



            Conclusion:




            1. When you declare a variable using 'var' outside a function ,it becomes global variable(you can check by typing i or
              window.i in console window.It will return 3).

            2. The annominous function you declared will not call and check the value inside the function unless you invoke the
              functions.

            3. When you invoke the function , console.log("My value: " + i) takes the value from its Global object and display the
              result.


            CASE2 : using let



            Now replace the 'var' with 'let'



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


            Do the same thing, Go to the scopes . Now you will see two objects "Block" and "Global". Now expand Block object , you
            will see 'i' is defined there , and the strange thing is that , for every functions , the value if i is different (0 , 1, 2).



            enter image description here



            Conclusion:



            When you declare variable using 'let' even outside the function but inside the loop , this variable will not be a Global
            variable , it will become a Block level variable which is only available for the same function only.That is the reason , we
            are getting value of i different for each function when we invoke the functions.



            For more detail about how closer works , please go through the awesome video tutorial https://youtu.be/71AtaJpJHw0






            share|improve this answer































              4














              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.






              share|improve this answer































                4














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



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





                share|improve this answer































                  3














                  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.






                  share|improve this answer























                  • 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
                    Dec 17 '15 at 14:24












                  • Now it's clear?
                    – Rax Wunter
                    Dec 17 '15 at 14:28










                  • It's related exactly to the mentioned issue: how to iterate safely without closure problems
                    – Rax Wunter
                    Dec 17 '15 at 14:31










                  • Now it doesn't seem significantly different from the accepted answer.
                    – Quentin
                    Dec 17 '15 at 14:31










                  • 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
                    Dec 17 '15 at 14:34





















                  3














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





                  share|improve this answer





























                    2














                    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 :)






                    share|improve this answer



















                    • 1




                      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
                      Jun 18 '15 at 18:21






                    • 1




                      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
                      Oct 27 '15 at 4:07






                    • 1




                      @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
                      Oct 27 '15 at 10:17



















                    2














                    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.






                    share|improve this answer































                      2














                      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 the browser.



                      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 the performance gain in different browsers.






                      share|improve this answer























                      • @TinyGiant The example with function being returned is still currying optimised for performance. I wouldn't jump on arrow functions bandwagon like all the JavaScript bloggers. They look cool and clean but promote writing functions inline instead of using predefined functions. This can be a non-obvious trap in hot places. Another problem is that they are not just syntactic sugar because they are executing unnecessary bindings thus creating wrapping closures.
                        – Pawel
                        Dec 27 '17 at 1:52










                      • Warning to future readers: This answer inaccurately applies the term Currying. "Currying is when you break down a function that takes multiple arguments into a series of functions that take part of the arguments.". This code does nothing of the sort. All you've done here is take the code from the accepted answer, move some things around, change the style and naming a bit, then call it currying, which it categorically is not.
                        – Tiny Giant
                        Dec 27 '17 at 2:36



















                      2














                      Your 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 the first loop is created with the condition of 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 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 the 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 the value of i in each iteration.



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






                      share|improve this answer































                        1














                        COUNTER BEING A PRIMITIVE



                        Let's 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 the callback function accesses the value based on the 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 the 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 what's 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, the value of the loop index will not be preserved. This is to show that the values of an 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





                        share|improve this answer



























                          1 2
                          next


                          protected by Josh Crozier May 11 '14 at 3:11



                          Thank you for your interest in this question.
                          Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).



                          Would you like to answer one of these unanswered questions instead?














                          39 Answers
                          39






                          active

                          oldest

                          votes








                          39 Answers
                          39






                          active

                          oldest

                          votes









                          active

                          oldest

                          votes






                          active

                          oldest

                          votes








                          1 2
                          next










                          1892














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



                          Classic solution: Closures



                          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.





                          2015 Solution: forEach



                          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.





                          ES6 solution: let



                          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.






                          share|improve this answer



















                          • 7




                            isn't function createfunc(i) { return function() { console.log("My value: " + i); }; } still closure because it uses the variable i?
                            – アレックス
                            Mar 28 '14 at 3:45






                          • 48




                            Unfortunately, this answer is outdated and nobody will see the correct answer at the bottom - using Function.bind() is definitely preferable by now, see stackoverflow.com/a/19323214/785541.
                            – Wladimir Palant
                            Jun 20 '14 at 12:21






                          • 67




                            @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
                            Jul 12 '14 at 2:35






                          • 7




                            Please stop using these for-return function hacks, use .forEach or .map instead because they avoid reusing the same scope variables.
                            – Christian Landgren
                            Feb 7 '15 at 10:23






                          • 23




                            @ChristianLandgren: That's only useful if you're iterating an Array. These techniques aren't "hacks". They're essential knowledge.
                            – user1106925
                            Jun 29 '15 at 16:31
















                          1892














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



                          Classic solution: Closures



                          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.





                          2015 Solution: forEach



                          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.





                          ES6 solution: let



                          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.






                          share|improve this answer



















                          • 7




                            isn't function createfunc(i) { return function() { console.log("My value: " + i); }; } still closure because it uses the variable i?
                            – アレックス
                            Mar 28 '14 at 3:45






                          • 48




                            Unfortunately, this answer is outdated and nobody will see the correct answer at the bottom - using Function.bind() is definitely preferable by now, see stackoverflow.com/a/19323214/785541.
                            – Wladimir Palant
                            Jun 20 '14 at 12:21






                          • 67




                            @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
                            Jul 12 '14 at 2:35






                          • 7




                            Please stop using these for-return function hacks, use .forEach or .map instead because they avoid reusing the same scope variables.
                            – Christian Landgren
                            Feb 7 '15 at 10:23






                          • 23




                            @ChristianLandgren: That's only useful if you're iterating an Array. These techniques aren't "hacks". They're essential knowledge.
                            – user1106925
                            Jun 29 '15 at 16:31














                          1892












                          1892








                          1892






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



                          Classic solution: Closures



                          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.





                          2015 Solution: forEach



                          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.





                          ES6 solution: let



                          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.






                          share|improve this answer














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



                          Classic solution: Closures



                          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.





                          2015 Solution: forEach



                          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.





                          ES6 solution: let



                          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.






                          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
                          }





                          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
                          }






                          share|improve this answer














                          share|improve this answer



                          share|improve this answer








                          edited Jun 6 at 10:19









                          Quentin

                          638k718611031




                          638k718611031










                          answered Apr 15 '09 at 6:18









                          harto

                          72.3k53859




                          72.3k53859








                          • 7




                            isn't function createfunc(i) { return function() { console.log("My value: " + i); }; } still closure because it uses the variable i?
                            – アレックス
                            Mar 28 '14 at 3:45






                          • 48




                            Unfortunately, this answer is outdated and nobody will see the correct answer at the bottom - using Function.bind() is definitely preferable by now, see stackoverflow.com/a/19323214/785541.
                            – Wladimir Palant
                            Jun 20 '14 at 12:21






                          • 67




                            @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
                            Jul 12 '14 at 2:35






                          • 7




                            Please stop using these for-return function hacks, use .forEach or .map instead because they avoid reusing the same scope variables.
                            – Christian Landgren
                            Feb 7 '15 at 10:23






                          • 23




                            @ChristianLandgren: That's only useful if you're iterating an Array. These techniques aren't "hacks". They're essential knowledge.
                            – user1106925
                            Jun 29 '15 at 16:31














                          • 7




                            isn't function createfunc(i) { return function() { console.log("My value: " + i); }; } still closure because it uses the variable i?
                            – アレックス
                            Mar 28 '14 at 3:45






                          • 48




                            Unfortunately, this answer is outdated and nobody will see the correct answer at the bottom - using Function.bind() is definitely preferable by now, see stackoverflow.com/a/19323214/785541.
                            – Wladimir Palant
                            Jun 20 '14 at 12:21






                          • 67




                            @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
                            Jul 12 '14 at 2:35






                          • 7




                            Please stop using these for-return function hacks, use .forEach or .map instead because they avoid reusing the same scope variables.
                            – Christian Landgren
                            Feb 7 '15 at 10:23






                          • 23




                            @ChristianLandgren: That's only useful if you're iterating an Array. These techniques aren't "hacks". They're essential knowledge.
                            – user1106925
                            Jun 29 '15 at 16:31








                          7




                          7




                          isn't function createfunc(i) { return function() { console.log("My value: " + i); }; } still closure because it uses the variable i?
                          – アレックス
                          Mar 28 '14 at 3:45




                          isn't function createfunc(i) { return function() { console.log("My value: " + i); }; } still closure because it uses the variable i?
                          – アレックス
                          Mar 28 '14 at 3:45




                          48




                          48




                          Unfortunately, this answer is outdated and nobody will see the correct answer at the bottom - using Function.bind() is definitely preferable by now, see stackoverflow.com/a/19323214/785541.
                          – Wladimir Palant
                          Jun 20 '14 at 12:21




                          Unfortunately, this answer is outdated and nobody will see the correct answer at the bottom - using Function.bind() is definitely preferable by now, see stackoverflow.com/a/19323214/785541.
                          – Wladimir Palant
                          Jun 20 '14 at 12:21




                          67




                          67




                          @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
                          Jul 12 '14 at 2:35




                          @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
                          Jul 12 '14 at 2:35




                          7




                          7




                          Please stop using these for-return function hacks, use .forEach or .map instead because they avoid reusing the same scope variables.
                          – Christian Landgren
                          Feb 7 '15 at 10:23




                          Please stop using these for-return function hacks, use .forEach or .map instead because they avoid reusing the same scope variables.
                          – Christian Landgren
                          Feb 7 '15 at 10:23




                          23




                          23




                          @ChristianLandgren: That's only useful if you're iterating an Array. These techniques aren't "hacks". They're essential knowledge.
                          – user1106925
                          Jun 29 '15 at 16:31




                          @ChristianLandgren: That's only useful if you're iterating an Array. These techniques aren't "hacks". They're essential knowledge.
                          – user1106925
                          Jun 29 '15 at 16:31













                          349














                          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.






                          share|improve this answer























                          • any explanation about the }(i)); ?
                            – aswzen
                            Apr 6 at 1:32






                          • 3




                            @aswzen I think it passes i as the argument index to the function.
                            – Jet Blue
                            Jul 26 at 22:01
















                          349














                          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.






                          share|improve this answer























                          • any explanation about the }(i)); ?
                            – aswzen
                            Apr 6 at 1:32






                          • 3




                            @aswzen I think it passes i as the argument index to the function.
                            – Jet Blue
                            Jul 26 at 22:01














                          349












                          349








                          349






                          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.






                          share|improve this answer














                          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.







                          share|improve this answer














                          share|improve this answer



                          share|improve this answer








                          edited May 23 '17 at 12:18









                          Community

                          11




                          11










                          answered Apr 15 '09 at 6:10









                          Bjorn Tipling

                          35.8k33118158




                          35.8k33118158












                          • any explanation about the }(i)); ?
                            – aswzen
                            Apr 6 at 1:32






                          • 3




                            @aswzen I think it passes i as the argument index to the function.
                            – Jet Blue
                            Jul 26 at 22:01


















                          • any explanation about the }(i)); ?
                            – aswzen
                            Apr 6 at 1:32






                          • 3




                            @aswzen I think it passes i as the argument index to the function.
                            – Jet Blue
                            Jul 26 at 22:01
















                          any explanation about the }(i)); ?
                          – aswzen
                          Apr 6 at 1:32




                          any explanation about the }(i)); ?
                          – aswzen
                          Apr 6 at 1:32




                          3




                          3




                          @aswzen I think it passes i as the argument index to the function.
                          – Jet Blue
                          Jul 26 at 22:01




                          @aswzen I think it passes i as the argument index to the function.
                          – Jet Blue
                          Jul 26 at 22:01











                          320














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





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








                          share|improve this answer























                          • This is what I do these days too, I also like lo-dash/underscore's _.partial
                            – Bjorn Tipling
                            Dec 8 '14 at 5:18






                          • 16




                            .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
                            Jun 28 '15 at 3:29










                          • 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
                            Jun 28 '15 at 18:32






                          • 4




                            @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
                            Jun 29 '15 at 16:23






                          • 4




                            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
                            Sep 11 '15 at 12:14


















                          320














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





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








                          share|improve this answer























                          • This is what I do these days too, I also like lo-dash/underscore's _.partial
                            – Bjorn Tipling
                            Dec 8 '14 at 5:18






                          • 16




                            .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
                            Jun 28 '15 at 3:29










                          • 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
                            Jun 28 '15 at 18:32






                          • 4




                            @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
                            Jun 29 '15 at 16:23






                          • 4




                            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
                            Sep 11 '15 at 12:14
















                          320












                          320








                          320






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





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








                          share|improve this answer














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





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








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





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





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





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






                          share|improve this answer














                          share|improve this answer



                          share|improve this answer








                          edited Feb 21 at 16:03









                          Håken Lid

                          10.6k62442




                          10.6k62442










                          answered Oct 11 '13 at 16:41









                          Aust

                          7,334103564




                          7,334103564












                          • This is what I do these days too, I also like lo-dash/underscore's _.partial
                            – Bjorn Tipling
                            Dec 8 '14 at 5:18






                          • 16




                            .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
                            Jun 28 '15 at 3:29










                          • 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
                            Jun 28 '15 at 18:32






                          • 4




                            @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
                            Jun 29 '15 at 16:23






                          • 4




                            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
                            Sep 11 '15 at 12:14




















                          • This is what I do these days too, I also like lo-dash/underscore's _.partial
                            – Bjorn Tipling
                            Dec 8 '14 at 5:18






                          • 16




                            .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
                            Jun 28 '15 at 3:29










                          • 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
                            Jun 28 '15 at 18:32






                          • 4




                            @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
                            Jun 29 '15 at 16:23






                          • 4




                            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
                            Sep 11 '15 at 12:14


















                          This is what I do these days too, I also like lo-dash/underscore's _.partial
                          – Bjorn Tipling
                          Dec 8 '14 at 5:18




                          This is what I do these days too, I also like lo-dash/underscore's _.partial
                          – Bjorn Tipling
                          Dec 8 '14 at 5:18




                          16




                          16




                          .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
                          Jun 28 '15 at 3:29




                          .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
                          Jun 28 '15 at 3:29












                          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
                          Jun 28 '15 at 18:32




                          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
                          Jun 28 '15 at 18:32




                          4




                          4




                          @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
                          Jun 29 '15 at 16:23




                          @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
                          Jun 29 '15 at 16:23




                          4




                          4




                          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
                          Sep 11 '15 at 12:14






                          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
                          Sep 11 '15 at 12:14













                          243














                          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.






                          share|improve this answer



















                          • 8




                            For further code readability and to avoid confusion as to which i is what, I'd rename the function parameter to index.
                            – Kyle Falconer
                            Jan 10 '14 at 16:45






                          • 4




                            How would you use this technique to define the array funcs described in the original question?
                            – Nico
                            Nov 30 '14 at 13:17










                          • @Nico The same way as shown in the original question, except you would use index instead of i.
                            – JLRishe
                            Mar 31 '15 at 20:54










                          • @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
                            Apr 1 '15 at 9:22








                          • 1




                            @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
                            Apr 1 '15 at 10:05


















                          243














                          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.






                          share|improve this answer



















                          • 8




                            For further code readability and to avoid confusion as to which i is what, I'd rename the function parameter to index.
                            – Kyle Falconer
                            Jan 10 '14 at 16:45






                          • 4




                            How would you use this technique to define the array funcs described in the original question?
                            – Nico
                            Nov 30 '14 at 13:17










                          • @Nico The same way as shown in the original question, except you would use index instead of i.
                            – JLRishe
                            Mar 31 '15 at 20:54










                          • @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
                            Apr 1 '15 at 9:22








                          • 1




                            @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
                            Apr 1 '15 at 10:05
















                          243












                          243








                          243






                          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.






                          share|improve this answer














                          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.







                          share|improve this answer














                          share|improve this answer



                          share|improve this answer








                          edited Sep 22 '15 at 13:47

























                          answered Oct 11 '13 at 18:23









                          neurosnap

                          3,36321521




                          3,36321521








                          • 8




                            For further code readability and to avoid confusion as to which i is what, I'd rename the function parameter to index.
                            – Kyle Falconer
                            Jan 10 '14 at 16:45






                          • 4




                            How would you use this technique to define the array funcs described in the original question?
                            – Nico
                            Nov 30 '14 at 13:17










                          • @Nico The same way as shown in the original question, except you would use index instead of i.
                            – JLRishe
                            Mar 31 '15 at 20:54










                          • @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
                            Apr 1 '15 at 9:22








                          • 1




                            @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
                            Apr 1 '15 at 10:05
















                          • 8




                            For further code readability and to avoid confusion as to which i is what, I'd rename the function parameter to index.
                            – Kyle Falconer
                            Jan 10 '14 at 16:45






                          • 4




                            How would you use this technique to define the array funcs described in the original question?
                            – Nico
                            Nov 30 '14 at 13:17










                          • @Nico The same way as shown in the original question, except you would use index instead of i.
                            – JLRishe
                            Mar 31 '15 at 20:54










                          • @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
                            Apr 1 '15 at 9:22








                          • 1




                            @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
                            Apr 1 '15 at 10:05










                          8




                          8




                          For further code readability and to avoid confusion as to which i is what, I'd rename the function parameter to index.
                          – Kyle Falconer
                          Jan 10 '14 at 16:45




                          For further code readability and to avoid confusion as to which i is what, I'd rename the function parameter to index.
                          – Kyle Falconer
                          Jan 10 '14 at 16:45




                          4




                          4




                          How would you use this technique to define the array funcs described in the original question?
                          – Nico
                          Nov 30 '14 at 13:17




                          How would you use this technique to define the array funcs described in the original question?
                          – Nico
                          Nov 30 '14 at 13:17












                          @Nico The same way as shown in the original question, except you would use index instead of i.
                          – JLRishe
                          Mar 31 '15 at 20:54




                          @Nico The same way as shown in the original question, except you would use index instead of i.
                          – JLRishe
                          Mar 31 '15 at 20:54












                          @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
                          Apr 1 '15 at 9:22






                          @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
                          Apr 1 '15 at 9:22






                          1




                          1




                          @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
                          Apr 1 '15 at 10:05






                          @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
                          Apr 1 '15 at 10:05













                          137














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





                          Update



                          With ES6 now mainstream, we can now use the new let keyword to create block-scoped variables:






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

                          var funcs = {};
                          for (let i = 0; i < 3; i++) { // use "let" to declare "i"
                          funcs[i] = function() {
                          console.log("My value: " + i); //each should reference its own local variable
                          };
                          }
                          for (var j = 0; j < 3; j++) { // we can use "var" here without issue
                          funcs[j]();
                          }





                          Look how easy it is now! For more information see this answer, which my info is based off of.






                          share|improve this answer























                          • I like how you explained the IIFE way as well. I was looking for that. Thank you.
                            – CapturedTree
                            Oct 26 '17 at 21:45






                          • 3




                            There is now such a thing as block scoping in JavaScript using the let and const keywords. If this answer were to expand to include that, it would be much more globally useful in my opinion.
                            – Tiny Giant
                            Dec 27 '17 at 3:12










                          • @TinyGiant sure thing, I added some info about let and linked a more complete explanation
                            – woojoo666
                            Mar 1 at 22:44










                          • @woojoo666 Could your answer also work for calling two alternating URL's in a loop like so: i=0; while(i < 100) { setTimeout(function(){ window.open("https://www.bbc.com","_self") }, 3000); setTimeout(function(){ window.open("https://www.cnn.com","_self") }, 3000); i++ }? (could replace window.open() with getelementbyid......)
                            – nutty about natty
                            May 14 at 19:08












                          • @nuttyaboutnatty sorry about such a late reply. It doesn't seem like the code in your example already works. You aren't using i in your timeout functions, so you don't need a closure
                            – woojoo666
                            Jun 3 at 22:58
















                          137














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





                          Update



                          With ES6 now mainstream, we can now use the new let keyword to create block-scoped variables:






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

                          var funcs = {};
                          for (let i = 0; i < 3; i++) { // use "let" to declare "i"
                          funcs[i] = function() {
                          console.log("My value: " + i); //each should reference its own local variable
                          };
                          }
                          for (var j = 0; j < 3; j++) { // we can use "var" here without issue
                          funcs[j]();
                          }





                          Look how easy it is now! For more information see this answer, which my info is based off of.






                          share|improve this answer























                          • I like how you explained the IIFE way as well. I was looking for that. Thank you.
                            – CapturedTree
                            Oct 26 '17 at 21:45






                          • 3




                            There is now such a thing as block scoping in JavaScript using the let and const keywords. If this answer were to expand to include that, it would be much more globally useful in my opinion.
                            – Tiny Giant
                            Dec 27 '17 at 3:12










                          • @TinyGiant sure thing, I added some info about let and linked a more complete explanation
                            – woojoo666
                            Mar 1 at 22:44










                          • @woojoo666 Could your answer also work for calling two alternating URL's in a loop like so: i=0; while(i < 100) { setTimeout(function(){ window.open("https://www.bbc.com","_self") }, 3000); setTimeout(function(){ window.open("https://www.cnn.com","_self") }, 3000); i++ }? (could replace window.open() with getelementbyid......)
                            – nutty about natty
                            May 14 at 19:08












                          • @nuttyaboutnatty sorry about such a late reply. It doesn't seem like the code in your example already works. You aren't using i in your timeout functions, so you don't need a closure
                            – woojoo666
                            Jun 3 at 22:58














                          137












                          137








                          137






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





                          Update



                          With ES6 now mainstream, we can now use the new let keyword to create block-scoped variables:






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

                          var funcs = {};
                          for (let i = 0; i < 3; i++) { // use "let" to declare "i"
                          funcs[i] = function() {
                          console.log("My value: " + i); //each should reference its own local variable
                          };
                          }
                          for (var j = 0; j < 3; j++) { // we can use "var" here without issue
                          funcs[j]();
                          }





                          Look how easy it is now! For more information see this answer, which my info is based off of.






                          share|improve this answer














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





                          Update



                          With ES6 now mainstream, we can now use the new let keyword to create block-scoped variables:






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

                          var funcs = {};
                          for (let i = 0; i < 3; i++) { // use "let" to declare "i"
                          funcs[i] = function() {
                          console.log("My value: " + i); //each should reference its own local variable
                          };
                          }
                          for (var j = 0; j < 3; j++) { // we can use "var" here without issue
                          funcs[j]();
                          }





                          Look how easy it is now! For more information see this answer, which my info is based off of.






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





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





                          //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;
                          }





                          //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;
                          }





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





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





                          //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);
                          };
                          }





                          //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);
                          };
                          }





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

                          var funcs = {};
                          for (let i = 0; i < 3; i++) { // use "let" to declare "i"
                          funcs[i] = function() {
                          console.log("My value: " + i); //each should reference its own local variable
                          };
                          }
                          for (var j = 0; j < 3; j++) { // we can use "var" here without issue
                          funcs[j]();
                          }





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

                          var funcs = {};
                          for (let i = 0; i < 3; i++) { // use "let" to declare "i"
                          funcs[i] = function() {
                          console.log("My value: " + i); //each should reference its own local variable
                          };
                          }
                          for (var j = 0; j < 3; j++) { // we can use "var" here without issue
                          funcs[j]();
                          }






                          share|improve this answer














                          share|improve this answer



                          share|improve this answer








                          edited Mar 1 at 22:43

























                          answered Apr 10 '15 at 9:57









                          woojoo666

                          4,95052642




                          4,95052642












                          • I like how you explained the IIFE way as well. I was looking for that. Thank you.
                            – CapturedTree
                            Oct 26 '17 at 21:45






                          • 3




                            There is now such a thing as block scoping in JavaScript using the let and const keywords. If this answer were to expand to include that, it would be much more globally useful in my opinion.
                            – Tiny Giant
                            Dec 27 '17 at 3:12










                          • @TinyGiant sure thing, I added some info about let and linked a more complete explanation
                            – woojoo666
                            Mar 1 at 22:44










                          • @woojoo666 Could your answer also work for calling two alternating URL's in a loop like so: i=0; while(i < 100) { setTimeout(function(){ window.open("https://www.bbc.com","_self") }, 3000); setTimeout(function(){ window.open("https://www.cnn.com","_self") }, 3000); i++ }? (could replace window.open() with getelementbyid......)
                            – nutty about natty
                            May 14 at 19:08












                          • @nuttyaboutnatty sorry about such a late reply. It doesn't seem like the code in your example already works. You aren't using i in your timeout functions, so you don't need a closure
                            – woojoo666
                            Jun 3 at 22:58


















                          • I like how you explained the IIFE way as well. I was looking for that. Thank you.
                            – CapturedTree
                            Oct 26 '17 at 21:45






                          • 3




                            There is now such a thing as block scoping in JavaScript using the let and const keywords. If this answer were to expand to include that, it would be much more globally useful in my opinion.
                            – Tiny Giant
                            Dec 27 '17 at 3:12










                          • @TinyGiant sure thing, I added some info about let and linked a more complete explanation
                            – woojoo666
                            Mar 1 at 22:44










                          • @woojoo666 Could your answer also work for calling two alternating URL's in a loop like so: i=0; while(i < 100) { setTimeout(function(){ window.open("https://www.bbc.com","_self") }, 3000); setTimeout(function(){ window.open("https://www.cnn.com","_self") }, 3000); i++ }? (could replace window.open() with getelementbyid......)
                            – nutty about natty
                            May 14 at 19:08












                          • @nuttyaboutnatty sorry about such a late reply. It doesn't seem like the code in your example already works. You aren't using i in your timeout functions, so you don't need a closure
                            – woojoo666
                            Jun 3 at 22:58
















                          I like how you explained the IIFE way as well. I was looking for that. Thank you.
                          – CapturedTree
                          Oct 26 '17 at 21:45




                          I like how you explained the IIFE way as well. I was looking for that. Thank you.
                          – CapturedTree
                          Oct 26 '17 at 21:45




                          3




                          3




                          There is now such a thing as block scoping in JavaScript using the let and const keywords. If this answer were to expand to include that, it would be much more globally useful in my opinion.
                          – Tiny Giant
                          Dec 27 '17 at 3:12




                          There is now such a thing as block scoping in JavaScript using the let and const keywords. If this answer were to expand to include that, it would be much more globally useful in my opinion.
                          – Tiny Giant
                          Dec 27 '17 at 3:12












                          @TinyGiant sure thing, I added some info about let and linked a more complete explanation
                          – woojoo666
                          Mar 1 at 22:44




                          @TinyGiant sure thing, I added some info about let and linked a more complete explanation
                          – woojoo666
                          Mar 1 at 22:44












                          @woojoo666 Could your answer also work for calling two alternating URL's in a loop like so: i=0; while(i < 100) { setTimeout(function(){ window.open("https://www.bbc.com","_self") }, 3000); setTimeout(function(){ window.open("https://www.cnn.com","_self") }, 3000); i++ }? (could replace window.open() with getelementbyid......)
                          – nutty about natty
                          May 14 at 19:08






                          @woojoo666 Could your answer also work for calling two alternating URL's in a loop like so: i=0; while(i < 100) { setTimeout(function(){ window.open("https://www.bbc.com","_self") }, 3000); setTimeout(function(){ window.open("https://www.cnn.com","_self") }, 3000); i++ }? (could replace window.open() with getelementbyid......)
                          – nutty about natty
                          May 14 at 19:08














                          @nuttyaboutnatty sorry about such a late reply. It doesn't seem like the code in your example already works. You aren't using i in your timeout functions, so you don't need a closure
                          – woojoo666
                          Jun 3 at 22:58




                          @nuttyaboutnatty sorry about such a late reply. It doesn't seem like the code in your example already works. You aren't using i in your timeout functions, so you don't need a closure
                          – woojoo666
                          Jun 3 at 22:58











                          128














                          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:




                          • const

                          • let


                          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.






                          share|improve this answer























                          • Unfortunately, 'let' is still not fully supported, especially in mobile. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
                            – MattC
                            Feb 23 '16 at 17:47






                          • 2




                            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
                            Jun 22 '16 at 10:18












                          • @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
                            Jun 27 '16 at 14:24












                          • Isn't this why we use babel to transpile our code so browsers that don't support ES6/7 can understand what's going on?
                            – pixel 67
                            Mar 19 at 15:56
















                          128














                          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:




                          • const

                          • let


                          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.






                          share|improve this answer























                          • Unfortunately, 'let' is still not fully supported, especially in mobile. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
                            – MattC
                            Feb 23 '16 at 17:47






                          • 2




                            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
                            Jun 22 '16 at 10:18












                          • @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
                            Jun 27 '16 at 14:24












                          • Isn't this why we use babel to transpile our code so browsers that don't support ES6/7 can understand what's going on?
                            – pixel 67
                            Mar 19 at 15:56














                          128












                          128








                          128






                          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:




                          • const

                          • let


                          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.






                          share|improve this answer














                          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:




                          • const

                          • let


                          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.







                          share|improve this answer














                          share|improve this answer



                          share|improve this answer








                          edited Apr 11 at 17:05

























                          answered May 21 '13 at 3:04









                          Ben McCormick

                          18.3k93965




                          18.3k93965












                          • Unfortunately, 'let' is still not fully supported, especially in mobile. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
                            – MattC
                            Feb 23 '16 at 17:47






                          • 2




                            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
                            Jun 22 '16 at 10:18












                          • @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
                            Jun 27 '16 at 14:24












                          • Isn't this why we use babel to transpile our code so browsers that don't support ES6/7 can understand what's going on?
                            – pixel 67
                            Mar 19 at 15:56


















                          • Unfortunately, 'let' is still not fully supported, especially in mobile. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
                            – MattC
                            Feb 23 '16 at 17:47






                          • 2




                            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
                            Jun 22 '16 at 10:18












                          • @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
                            Jun 27 '16 at 14:24












                          • Isn't this why we use babel to transpile our code so browsers that don't support ES6/7 can understand what's going on?
                            – pixel 67
                            Mar 19 at 15:56
















                          Unfortunately, 'let' is still not fully supported, especially in mobile. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
                          – MattC
                          Feb 23 '16 at 17:47




                          Unfortunately, 'let' is still not fully supported, especially in mobile. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
                          – MattC
                          Feb 23 '16 at 17:47




                          2




                          2




                          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
                          Jun 22 '16 at 10:18






                          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
                          Jun 22 '16 at 10:18














                          @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
                          Jun 27 '16 at 14:24






                          @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
                          Jun 27 '16 at 14:24














                          Isn't this why we use babel to transpile our code so browsers that don't support ES6/7 can understand what's going on?
                          – pixel 67
                          Mar 19 at 15:56




                          Isn't this why we use babel to transpile our code so browsers that don't support ES6/7 can understand what's going on?
                          – pixel 67
                          Mar 19 at 15:56











                          79














                          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 the value for 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).






                          share|improve this answer




























                            79














                            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 the value for 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).






                            share|improve this answer


























                              79












                              79








                              79






                              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 the value for 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).






                              share|improve this answer














                              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 the value for 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).







                              share|improve this answer














                              share|improve this answer



                              share|improve this answer








                              edited Dec 26 '17 at 11:07









                              Nae

                              5,58731136




                              5,58731136










                              answered Apr 15 '09 at 6:48









                              Darren Clark

                              2,4591413




                              2,4591413























                                  62














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





                                  share|improve this answer























                                  • @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
                                    Apr 15 '09 at 6:54






                                  • 1




                                    @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
                                    Apr 16 '09 at 2:55






                                  • 2




                                    @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
                                    Apr 16 '09 at 2:58






                                  • 4




                                    See also What browsers currently support javascript's 'let' keyword?
                                    – rds
                                    Jan 15 '13 at 10:21






                                  • 1




                                    Do not use let then
                                    – regisbsb
                                    Oct 14 '13 at 17:13
















                                  62














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





                                  share|improve this answer























                                  • @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
                                    Apr 15 '09 at 6:54






                                  • 1




                                    @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
                                    Apr 16 '09 at 2:55






                                  • 2




                                    @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
                                    Apr 16 '09 at 2:58






                                  • 4




                                    See also What browsers currently support javascript's 'let' keyword?
                                    – rds
                                    Jan 15 '13 at 10:21






                                  • 1




                                    Do not use let then
                                    – regisbsb
                                    Oct 14 '13 at 17:13














                                  62












                                  62








                                  62






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





                                  share|improve this answer














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






                                  share|improve this answer














                                  share|improve this answer



                                  share|improve this answer








                                  edited Apr 15 '09 at 6:31

























                                  answered Apr 15 '09 at 6:25









                                  eglasius

                                  32.8k450105




                                  32.8k450105












                                  • @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
                                    Apr 15 '09 at 6:54






                                  • 1




                                    @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
                                    Apr 16 '09 at 2:55






                                  • 2




                                    @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
                                    Apr 16 '09 at 2:58






                                  • 4




                                    See also What browsers currently support javascript's 'let' keyword?
                                    – rds
                                    Jan 15 '13 at 10:21






                                  • 1




                                    Do not use let then
                                    – regisbsb
                                    Oct 14 '13 at 17:13


















                                  • @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
                                    Apr 15 '09 at 6:54






                                  • 1




                                    @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
                                    Apr 16 '09 at 2:55






                                  • 2




                                    @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
                                    Apr 16 '09 at 2:58






                                  • 4




                                    See also What browsers currently support javascript's 'let' keyword?
                                    – rds
                                    Jan 15 '13 at 10:21






                                  • 1




                                    Do not use let then
                                    – regisbsb
                                    Oct 14 '13 at 17:13
















                                  @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
                                  Apr 15 '09 at 6:54




                                  @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
                                  Apr 15 '09 at 6:54




                                  1




                                  1




                                  @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
                                  Apr 16 '09 at 2:55




                                  @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
                                  Apr 16 '09 at 2:55




                                  2




                                  2




                                  @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
                                  Apr 16 '09 at 2:58




                                  @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
                                  Apr 16 '09 at 2:58




                                  4




                                  4




                                  See also What browsers currently support javascript's 'let' keyword?
                                  – rds
                                  Jan 15 '13 at 10:21




                                  See also What browsers currently support javascript's 'let' keyword?
                                  – rds
                                  Jan 15 '13 at 10:21




                                  1




                                  1




                                  Do not use let then
                                  – regisbsb
                                  Oct 14 '13 at 17:13




                                  Do not use let then
                                  – regisbsb
                                  Oct 14 '13 at 17:13











                                  50














                                  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.






                                  share|improve this answer





















                                  • 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
                                    Dec 3 '13 at 2:56










                                  • @midnite If you swapped var and return then the variable wouldn't be assigned before it returned the inner function.
                                    – Boann
                                    Dec 3 '13 at 4:35


















                                  50














                                  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.






                                  share|improve this answer





















                                  • 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
                                    Dec 3 '13 at 2:56










                                  • @midnite If you swapped var and return then the variable wouldn't be assigned before it returned the inner function.
                                    – Boann
                                    Dec 3 '13 at 4:35
















                                  50












                                  50








                                  50






                                  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.






                                  share|improve this answer












                                  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.







                                  share|improve this answer












                                  share|improve this answer



                                  share|improve this answer










                                  answered Aug 7 '12 at 8:45









                                  Boann

                                  36.7k1287121




                                  36.7k1287121












                                  • 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
                                    Dec 3 '13 at 2:56










                                  • @midnite If you swapped var and return then the variable wouldn't be assigned before it returned the inner function.
                                    – Boann
                                    Dec 3 '13 at 4:35




















                                  • 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
                                    Dec 3 '13 at 2:56










                                  • @midnite If you swapped var and return then the variable wouldn't be assigned before it returned the inner function.
                                    – Boann
                                    Dec 3 '13 at 4:35


















                                  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
                                  Dec 3 '13 at 2:56




                                  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
                                  Dec 3 '13 at 2:56












                                  @midnite If you swapped var and return then the variable wouldn't be assigned before it returned the inner function.
                                  – Boann
                                  Dec 3 '13 at 4:35






                                  @midnite If you swapped var and return then the variable wouldn't be assigned before it returned the inner function.
                                  – Boann
                                  Dec 3 '13 at 4:35













                                  46














                                  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






                                  share|improve this answer


























                                    46














                                    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






                                    share|improve this answer
























                                      46












                                      46








                                      46






                                      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






                                      share|improve this answer












                                      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







                                      share|improve this answer












                                      share|improve this answer



                                      share|improve this answer










                                      answered Apr 20 '13 at 9:59









                                      Mave

                                      1,3901932




                                      1,3901932























                                          42














                                          The most simple solution would be,



                                          Instead of using:



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

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


                                          which alerts "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 an 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 the anonymous function.



                                          This solution seems to fit any such problem since it will require minimal changes to the original code suffering from this issue. In fact, this is by design, it should not be an issue at all!






                                          share|improve this answer



















                                          • 2




                                            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
                                            Jul 26 '13 at 11:18








                                          • 1




                                            @DanMan Thanks. Self calling anonymous functions are very good way to deal javascript's lack of block level variable scope.
                                            – Kemal Dağ
                                            Jul 26 '13 at 12:20








                                          • 3




                                            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
                                            Oct 27 '15 at 4:29
















                                          42














                                          The most simple solution would be,



                                          Instead of using:



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

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


                                          which alerts "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 an 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 the anonymous function.



                                          This solution seems to fit any such problem since it will require minimal changes to the original code suffering from this issue. In fact, this is by design, it should not be an issue at all!






                                          share|improve this answer



















                                          • 2




                                            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
                                            Jul 26 '13 at 11:18








                                          • 1




                                            @DanMan Thanks. Self calling anonymous functions are very good way to deal javascript's lack of block level variable scope.
                                            – Kemal Dağ
                                            Jul 26 '13 at 12:20








                                          • 3




                                            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
                                            Oct 27 '15 at 4:29














                                          42












                                          42








                                          42






                                          The most simple solution would be,



                                          Instead of using:



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

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


                                          which alerts "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 an 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 the anonymous function.



                                          This solution seems to fit any such problem since it will require minimal changes to the original code suffering from this issue. In fact, this is by design, it should not be an issue at all!






                                          share|improve this answer














                                          The most simple solution would be,



                                          Instead of using:



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

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


                                          which alerts "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 an 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 the anonymous function.



                                          This solution seems to fit any such problem since it will require minimal changes to the original code suffering from this issue. In fact, this is by design, it should not be an issue at all!







                                          share|improve this answer














                                          share|improve this answer



                                          share|improve this answer








                                          edited Dec 28 '17 at 8:07

























                                          answered Jun 25 '13 at 14:21









                                          Kemal Dağ

                                          2,4281526




                                          2,4281526








                                          • 2




                                            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
                                            Jul 26 '13 at 11:18








                                          • 1




                                            @DanMan Thanks. Self calling anonymous functions are very good way to deal javascript's lack of block level variable scope.
                                            – Kemal Dağ
                                            Jul 26 '13 at 12:20








                                          • 3




                                            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
                                            Oct 27 '15 at 4:29














                                          • 2




                                            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
                                            Jul 26 '13 at 11:18








                                          • 1




                                            @DanMan Thanks. Self calling anonymous functions are very good way to deal javascript's lack of block level variable scope.
                                            – Kemal Dağ
                                            Jul 26 '13 at 12:20








                                          • 3




                                            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
                                            Oct 27 '15 at 4:29








                                          2




                                          2




                                          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
                                          Jul 26 '13 at 11:18






                                          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
                                          Jul 26 '13 at 11:18






                                          1




                                          1




                                          @DanMan Thanks. Self calling anonymous functions are very good way to deal javascript's lack of block level variable scope.
                                          – Kemal Dağ
                                          Jul 26 '13 at 12:20






                                          @DanMan Thanks. Self calling anonymous functions are very good way to deal javascript's lack of block level variable scope.
                                          – Kemal Dağ
                                          Jul 26 '13 at 12:20






                                          3




                                          3




                                          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
                                          Oct 27 '15 at 4:29




                                          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
                                          Oct 27 '15 at 4:29











                                          25














                                          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/






                                          share|improve this answer

















                                          • 1




                                            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ğ
                                            Jun 28 '15 at 8:51
















                                          25














                                          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/






                                          share|improve this answer

















                                          • 1




                                            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ğ
                                            Jun 28 '15 at 8:51














                                          25












                                          25








                                          25






                                          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/






                                          share|improve this answer












                                          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/







                                          share|improve this answer












                                          share|improve this answer



                                          share|improve this answer










                                          answered Sep 19 '13 at 14:20









                                          yilmazburk

                                          770815




                                          770815








                                          • 1




                                            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ğ
                                            Jun 28 '15 at 8:51














                                          • 1




                                            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ğ
                                            Jun 28 '15 at 8:51








                                          1




                                          1




                                          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ğ
                                          Jun 28 '15 at 8:51




                                          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ğ
                                          Jun 28 '15 at 8:51











                                          21














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





                                          share|improve this answer


























                                            21














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





                                            share|improve this answer
























                                              21












                                              21








                                              21






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





                                              share|improve this answer












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






                                              share|improve this answer












                                              share|improve this answer



                                              share|improve this answer










                                              answered Mar 5 '14 at 23:03









                                              Travis J

                                              63.7k28148222




                                              63.7k28148222























                                                  21














                                                  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






                                                  share|improve this answer























                                                  • forEach does not support IE8 or lower version !!!
                                                    – Bimal Das
                                                    Jan 16 at 13:16










                                                  • That's why I said "works back to IE9" ....
                                                    – Daryl
                                                    Jan 17 at 23:38
















                                                  21














                                                  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






                                                  share|improve this answer























                                                  • forEach does not support IE8 or lower version !!!
                                                    – Bimal Das
                                                    Jan 16 at 13:16










                                                  • That's why I said "works back to IE9" ....
                                                    – Daryl
                                                    Jan 17 at 23:38














                                                  21












                                                  21








                                                  21






                                                  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






                                                  share|improve this answer














                                                  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







                                                  share|improve this answer














                                                  share|improve this answer



                                                  share|improve this answer








                                                  edited Oct 29 at 22:48

























                                                  answered May 3 '14 at 3:42









                                                  Daryl

                                                  1,78832033




                                                  1,78832033












                                                  • forEach does not support IE8 or lower version !!!
                                                    – Bimal Das
                                                    Jan 16 at 13:16










                                                  • That's why I said "works back to IE9" ....
                                                    – Daryl
                                                    Jan 17 at 23:38


















                                                  • forEach does not support IE8 or lower version !!!
                                                    – Bimal Das
                                                    Jan 16 at 13:16










                                                  • That's why I said "works back to IE9" ....
                                                    – Daryl
                                                    Jan 17 at 23:38
















                                                  forEach does not support IE8 or lower version !!!
                                                  – Bimal Das
                                                  Jan 16 at 13:16




                                                  forEach does not support IE8 or lower version !!!
                                                  – Bimal Das
                                                  Jan 16 at 13:16












                                                  That's why I said "works back to IE9" ....
                                                  – Daryl
                                                  Jan 17 at 23:38




                                                  That's why I said "works back to IE9" ....
                                                  – Daryl
                                                  Jan 17 at 23:38











                                                  17














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






                                                  share|improve this answer



















                                                  • 1




                                                    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
                                                    Apr 5 '17 at 2:50
















                                                  17














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






                                                  share|improve this answer



















                                                  • 1




                                                    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
                                                    Apr 5 '17 at 2:50














                                                  17












                                                  17








                                                  17






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






                                                  share|improve this answer














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






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





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





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





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






                                                  share|improve this answer














                                                  share|improve this answer



                                                  share|improve this answer








                                                  edited Feb 15 '17 at 4:09

























                                                  answered Dec 7 '16 at 17:33









                                                  Costa

                                                  3,03544274




                                                  3,03544274








                                                  • 1




                                                    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
                                                    Apr 5 '17 at 2:50














                                                  • 1




                                                    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
                                                    Apr 5 '17 at 2:50








                                                  1




                                                  1




                                                  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
                                                  Apr 5 '17 at 2:50




                                                  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
                                                  Apr 5 '17 at 2:50











                                                  12














                                                  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.






                                                  share|improve this answer























                                                  • 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
                                                    Apr 26 '17 at 14:19
















                                                  12














                                                  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.






                                                  share|improve this answer























                                                  • 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
                                                    Apr 26 '17 at 14:19














                                                  12












                                                  12








                                                  12






                                                  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.






                                                  share|improve this answer














                                                  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.







                                                  share|improve this answer














                                                  share|improve this answer



                                                  share|improve this answer








                                                  edited May 23 '17 at 12:02









                                                  Community

                                                  11




                                                  11










                                                  answered Jul 14 '14 at 14:42









                                                  wpding

                                                  15615




                                                  15615












                                                  • 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
                                                    Apr 26 '17 at 14:19


















                                                  • 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
                                                    Apr 26 '17 at 14:19
















                                                  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
                                                  Apr 26 '17 at 14:19




                                                  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
                                                  Apr 26 '17 at 14:19











                                                  11














                                                  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
                                                  }


                                                  The code in OP's question is replaced with let instead of var.






                                                  share|improve this answer























                                                  • const provides the same result, and should be used when the value of a variable will not change. However, the use of const inside the initializer of the for loop is implemented incorrectly in Firefox and has yet to be fixed. Instead of being declared inside the block, it is declared outside the block, which results in a redeclaration to the variable, which in turn results in an error. The use of let inside the initializer is implemented correctly in Firefox, so no need to worry there.
                                                    – Tiny Giant
                                                    Dec 27 '17 at 3:05
















                                                  11














                                                  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
                                                  }


                                                  The code in OP's question is replaced with let instead of var.






                                                  share|improve this answer























                                                  • const provides the same result, and should be used when the value of a variable will not change. However, the use of const inside the initializer of the for loop is implemented incorrectly in Firefox and has yet to be fixed. Instead of being declared inside the block, it is declared outside the block, which results in a redeclaration to the variable, which in turn results in an error. The use of let inside the initializer is implemented correctly in Firefox, so no need to worry there.
                                                    – Tiny Giant
                                                    Dec 27 '17 at 3:05














                                                  11












                                                  11








                                                  11






                                                  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
                                                  }


                                                  The code in OP's question is replaced with let instead of var.






                                                  share|improve this answer














                                                  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
                                                  }


                                                  The code in OP's question is replaced with let instead of var.







                                                  share|improve this answer














                                                  share|improve this answer



                                                  share|improve this answer








                                                  edited Dec 26 '17 at 20:27









                                                  Nae

                                                  5,58731136




                                                  5,58731136










                                                  answered Nov 7 '16 at 11:25









                                                  Prithvi Uppalapati

                                                  557520




                                                  557520












                                                  • const provides the same result, and should be used when the value of a variable will not change. However, the use of const inside the initializer of the for loop is implemented incorrectly in Firefox and has yet to be fixed. Instead of being declared inside the block, it is declared outside the block, which results in a redeclaration to the variable, which in turn results in an error. The use of let inside the initializer is implemented correctly in Firefox, so no need to worry there.
                                                    – Tiny Giant
                                                    Dec 27 '17 at 3:05


















                                                  • const provides the same result, and should be used when the value of a variable will not change. However, the use of const inside the initializer of the for loop is implemented incorrectly in Firefox and has yet to be fixed. Instead of being declared inside the block, it is declared outside the block, which results in a redeclaration to the variable, which in turn results in an error. The use of let inside the initializer is implemented correctly in Firefox, so no need to worry there.
                                                    – Tiny Giant
                                                    Dec 27 '17 at 3:05
















                                                  const provides the same result, and should be used when the value of a variable will not change. However, the use of const inside the initializer of the for loop is implemented incorrectly in Firefox and has yet to be fixed. Instead of being declared inside the block, it is declared outside the block, which results in a redeclaration to the variable, which in turn results in an error. The use of let inside the initializer is implemented correctly in Firefox, so no need to worry there.
                                                  – Tiny Giant
                                                  Dec 27 '17 at 3:05




                                                  const provides the same result, and should be used when the value of a variable will not change. However, the use of const inside the initializer of the for loop is implemented incorrectly in Firefox and has yet to be fixed. Instead of being declared inside the block, it is declared outside the block, which results in a redeclaration to the variable, which in turn results in an error. The use of let inside the initializer is implemented correctly in Firefox, so no need to worry there.
                                                  – Tiny Giant
                                                  Dec 27 '17 at 3:05











                                                  7














                                                  I'm surprised no one yet has 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.






                                                  share|improve this answer



















                                                  • 3




                                                    .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
                                                    Mar 31 '15 at 19:59












                                                  • This question is not about loop over an array
                                                    – jherax
                                                    Oct 27 '15 at 4:14










                                                  • Well, he wants to create an array of functions, this example shows how to do that without involving a global variable.
                                                    – Christian Landgren
                                                    Nov 11 '15 at 21:25
















                                                  7














                                                  I'm surprised no one yet has 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.






                                                  share|improve this answer



















                                                  • 3




                                                    .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
                                                    Mar 31 '15 at 19:59












                                                  • This question is not about loop over an array
                                                    – jherax
                                                    Oct 27 '15 at 4:14










                                                  • Well, he wants to create an array of functions, this example shows how to do that without involving a global variable.
                                                    – Christian Landgren
                                                    Nov 11 '15 at 21:25














                                                  7












                                                  7








                                                  7






                                                  I'm surprised no one yet has 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.






                                                  share|improve this answer














                                                  I'm surprised no one yet has 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.







                                                  share|improve this answer














                                                  share|improve this answer



                                                  share|improve this answer








                                                  edited Dec 26 '17 at 19:51









                                                  Nae

                                                  5,58731136




                                                  5,58731136










                                                  answered Dec 9 '14 at 22:24









                                                  Christian Landgren

                                                  8,03732828




                                                  8,03732828








                                                  • 3




                                                    .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
                                                    Mar 31 '15 at 19:59












                                                  • This question is not about loop over an array
                                                    – jherax
                                                    Oct 27 '15 at 4:14










                                                  • Well, he wants to create an array of functions, this example shows how to do that without involving a global variable.
                                                    – Christian Landgren
                                                    Nov 11 '15 at 21:25














                                                  • 3




                                                    .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
                                                    Mar 31 '15 at 19:59












                                                  • This question is not about loop over an array
                                                    – jherax
                                                    Oct 27 '15 at 4:14










                                                  • Well, he wants to create an array of functions, this example shows how to do that without involving a global variable.
                                                    – Christian Landgren
                                                    Nov 11 '15 at 21:25








                                                  3




                                                  3




                                                  .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
                                                  Mar 31 '15 at 19:59






                                                  .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
                                                  Mar 31 '15 at 19:59














                                                  This question is not about loop over an array
                                                  – jherax
                                                  Oct 27 '15 at 4:14




                                                  This question is not about loop over an array
                                                  – jherax
                                                  Oct 27 '15 at 4:14












                                                  Well, he wants to create an array of functions, this example shows how to do that without involving a global variable.
                                                  – Christian Landgren
                                                  Nov 11 '15 at 21:25




                                                  Well, he wants to create an array of functions, this example shows how to do that without involving a global variable.
                                                  – Christian Landgren
                                                  Nov 11 '15 at 21:25











                                                  6














                                                  First of all, understand what's 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]();
                                                    }



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







                                                  share|improve this answer




























                                                    6














                                                    First of all, understand what's 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]();
                                                      }



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







                                                    share|improve this answer


























                                                      6












                                                      6








                                                      6






                                                      First of all, understand what's 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]();
                                                        }



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







                                                      share|improve this answer














                                                      First of all, understand what's 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]();
                                                        }



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








                                                      share|improve this answer














                                                      share|improve this answer



                                                      share|improve this answer








                                                      edited Dec 26 '17 at 22:46









                                                      YakovL

                                                      2,865102339




                                                      2,865102339










                                                      answered Nov 4 '16 at 7:46









                                                      Ali Kahoot

                                                      7861913




                                                      7861913























                                                          6














                                                          This question really shows the history of JavaScript! Now we can avoid block scoping with arrow functions and handle loops directly from DOM nodes using Object methods.






                                                          const funcs = [1, 2, 3].map(i => () => console.log(i));
                                                          funcs.map(fn => fn())








                                                          const buttons = document.getElementsByTagName("button");
                                                          Object
                                                          .keys(buttons)
                                                          .map(i => buttons[i].addEventListener('click', () => console.log(i)));

                                                          <button>0</button><br>
                                                          <button>1</button><br>
                                                          <button>2</button>








                                                          share|improve this answer


























                                                            6














                                                            This question really shows the history of JavaScript! Now we can avoid block scoping with arrow functions and handle loops directly from DOM nodes using Object methods.






                                                            const funcs = [1, 2, 3].map(i => () => console.log(i));
                                                            funcs.map(fn => fn())








                                                            const buttons = document.getElementsByTagName("button");
                                                            Object
                                                            .keys(buttons)
                                                            .map(i => buttons[i].addEventListener('click', () => console.log(i)));

                                                            <button>0</button><br>
                                                            <button>1</button><br>
                                                            <button>2</button>








                                                            share|improve this answer
























                                                              6












                                                              6








                                                              6






                                                              This question really shows the history of JavaScript! Now we can avoid block scoping with arrow functions and handle loops directly from DOM nodes using Object methods.






                                                              const funcs = [1, 2, 3].map(i => () => console.log(i));
                                                              funcs.map(fn => fn())








                                                              const buttons = document.getElementsByTagName("button");
                                                              Object
                                                              .keys(buttons)
                                                              .map(i => buttons[i].addEventListener('click', () => console.log(i)));

                                                              <button>0</button><br>
                                                              <button>1</button><br>
                                                              <button>2</button>








                                                              share|improve this answer












                                                              This question really shows the history of JavaScript! Now we can avoid block scoping with arrow functions and handle loops directly from DOM nodes using Object methods.






                                                              const funcs = [1, 2, 3].map(i => () => console.log(i));
                                                              funcs.map(fn => fn())








                                                              const buttons = document.getElementsByTagName("button");
                                                              Object
                                                              .keys(buttons)
                                                              .map(i => buttons[i].addEventListener('click', () => console.log(i)));

                                                              <button>0</button><br>
                                                              <button>1</button><br>
                                                              <button>2</button>








                                                              const funcs = [1, 2, 3].map(i => () => console.log(i));
                                                              funcs.map(fn => fn())





                                                              const funcs = [1, 2, 3].map(i => () => console.log(i));
                                                              funcs.map(fn => fn())





                                                              const buttons = document.getElementsByTagName("button");
                                                              Object
                                                              .keys(buttons)
                                                              .map(i => buttons[i].addEventListener('click', () => console.log(i)));

                                                              <button>0</button><br>
                                                              <button>1</button><br>
                                                              <button>2</button>





                                                              const buttons = document.getElementsByTagName("button");
                                                              Object
                                                              .keys(buttons)
                                                              .map(i => buttons[i].addEventListener('click', () => console.log(i)));

                                                              <button>0</button><br>
                                                              <button>1</button><br>
                                                              <button>2</button>






                                                              share|improve this answer












                                                              share|improve this answer



                                                              share|improve this answer










                                                              answered Jan 13 at 13:17









                                                              sidhuko

                                                              1,4941011




                                                              1,4941011























                                                                  6















                                                                  We will check , what actually happens when you declare var and let
                                                                  one by one.





                                                                  Case1 : using var



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


                                                                  Now open your chrome console window by pressing F12 and refresh the page.
                                                                  Expend every 3 functions inside the array.You will see an property called [[Scopes]].Expand that one. You will see one
                                                                  array object called "Global",expand that one. You will find a property 'i' declared into the object which having value 3.



                                                                  enter image description here



                                                                  enter image description here



                                                                  Conclusion:




                                                                  1. When you declare a variable using 'var' outside a function ,it becomes global variable(you can check by typing i or
                                                                    window.i in console window.It will return 3).

                                                                  2. The annominous function you declared will not call and check the value inside the function unless you invoke the
                                                                    functions.

                                                                  3. When you invoke the function , console.log("My value: " + i) takes the value from its Global object and display the
                                                                    result.


                                                                  CASE2 : using let



                                                                  Now replace the 'var' with 'let'



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


                                                                  Do the same thing, Go to the scopes . Now you will see two objects "Block" and "Global". Now expand Block object , you
                                                                  will see 'i' is defined there , and the strange thing is that , for every functions , the value if i is different (0 , 1, 2).



                                                                  enter image description here



                                                                  Conclusion:



                                                                  When you declare variable using 'let' even outside the function but inside the loop , this variable will not be a Global
                                                                  variable , it will become a Block level variable which is only available for the same function only.That is the reason , we
                                                                  are getting value of i different for each function when we invoke the functions.



                                                                  For more detail about how closer works , please go through the awesome video tutorial https://youtu.be/71AtaJpJHw0






                                                                  share|improve this answer




























                                                                    6















                                                                    We will check , what actually happens when you declare var and let
                                                                    one by one.





                                                                    Case1 : using var



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


                                                                    Now open your chrome console window by pressing F12 and refresh the page.
                                                                    Expend every 3 functions inside the array.You will see an property called [[Scopes]].Expand that one. You will see one
                                                                    array object called "Global",expand that one. You will find a property 'i' declared into the object which having value 3.



                                                                    enter image description here



                                                                    enter image description here



                                                                    Conclusion:




                                                                    1. When you declare a variable using 'var' outside a function ,it becomes global variable(you can check by typing i or
                                                                      window.i in console window.It will return 3).

                                                                    2. The annominous function you declared will not call and check the value inside the function unless you invoke the
                                                                      functions.

                                                                    3. When you invoke the function , console.log("My value: " + i) takes the value from its Global object and display the
                                                                      result.


                                                                    CASE2 : using let



                                                                    Now replace the 'var' with 'let'



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


                                                                    Do the same thing, Go to the scopes . Now you will see two objects "Block" and "Global". Now expand Block object , you
                                                                    will see 'i' is defined there , and the strange thing is that , for every functions , the value if i is different (0 , 1, 2).



                                                                    enter image description here



                                                                    Conclusion:



                                                                    When you declare variable using 'let' even outside the function but inside the loop , this variable will not be a Global
                                                                    variable , it will become a Block level variable which is only available for the same function only.That is the reason , we
                                                                    are getting value of i different for each function when we invoke the functions.



                                                                    For more detail about how closer works , please go through the awesome video tutorial https://youtu.be/71AtaJpJHw0






                                                                    share|improve this answer


























                                                                      6












                                                                      6








                                                                      6







                                                                      We will check , what actually happens when you declare var and let
                                                                      one by one.





                                                                      Case1 : using var



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


                                                                      Now open your chrome console window by pressing F12 and refresh the page.
                                                                      Expend every 3 functions inside the array.You will see an property called [[Scopes]].Expand that one. You will see one
                                                                      array object called "Global",expand that one. You will find a property 'i' declared into the object which having value 3.



                                                                      enter image description here



                                                                      enter image description here



                                                                      Conclusion:




                                                                      1. When you declare a variable using 'var' outside a function ,it becomes global variable(you can check by typing i or
                                                                        window.i in console window.It will return 3).

                                                                      2. The annominous function you declared will not call and check the value inside the function unless you invoke the
                                                                        functions.

                                                                      3. When you invoke the function , console.log("My value: " + i) takes the value from its Global object and display the
                                                                        result.


                                                                      CASE2 : using let



                                                                      Now replace the 'var' with 'let'



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


                                                                      Do the same thing, Go to the scopes . Now you will see two objects "Block" and "Global". Now expand Block object , you
                                                                      will see 'i' is defined there , and the strange thing is that , for every functions , the value if i is different (0 , 1, 2).



                                                                      enter image description here



                                                                      Conclusion:



                                                                      When you declare variable using 'let' even outside the function but inside the loop , this variable will not be a Global
                                                                      variable , it will become a Block level variable which is only available for the same function only.That is the reason , we
                                                                      are getting value of i different for each function when we invoke the functions.



                                                                      For more detail about how closer works , please go through the awesome video tutorial https://youtu.be/71AtaJpJHw0






                                                                      share|improve this answer















                                                                      We will check , what actually happens when you declare var and let
                                                                      one by one.





                                                                      Case1 : using var



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


                                                                      Now open your chrome console window by pressing F12 and refresh the page.
                                                                      Expend every 3 functions inside the array.You will see an property called [[Scopes]].Expand that one. You will see one
                                                                      array object called "Global",expand that one. You will find a property 'i' declared into the object which having value 3.



                                                                      enter image description here



                                                                      enter image description here



                                                                      Conclusion:




                                                                      1. When you declare a variable using 'var' outside a function ,it becomes global variable(you can check by typing i or
                                                                        window.i in console window.It will return 3).

                                                                      2. The annominous function you declared will not call and check the value inside the function unless you invoke the
                                                                        functions.

                                                                      3. When you invoke the function , console.log("My value: " + i) takes the value from its Global object and display the
                                                                        result.


                                                                      CASE2 : using let



                                                                      Now replace the 'var' with 'let'



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


                                                                      Do the same thing, Go to the scopes . Now you will see two objects "Block" and "Global". Now expand Block object , you
                                                                      will see 'i' is defined there , and the strange thing is that , for every functions , the value if i is different (0 , 1, 2).



                                                                      enter image description here



                                                                      Conclusion:



                                                                      When you declare variable using 'let' even outside the function but inside the loop , this variable will not be a Global
                                                                      variable , it will become a Block level variable which is only available for the same function only.That is the reason , we
                                                                      are getting value of i different for each function when we invoke the functions.



                                                                      For more detail about how closer works , please go through the awesome video tutorial https://youtu.be/71AtaJpJHw0







                                                                      share|improve this answer














                                                                      share|improve this answer



                                                                      share|improve this answer








                                                                      answered Jan 16 at 14:29


























                                                                      community wiki





                                                                      Bimal Das
























                                                                          4














                                                                          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.






                                                                          share|improve this answer




























                                                                            4














                                                                            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.






                                                                            share|improve this answer


























                                                                              4












                                                                              4








                                                                              4






                                                                              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.






                                                                              share|improve this answer














                                                                              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.







                                                                              share|improve this answer














                                                                              share|improve this answer



                                                                              share|improve this answer








                                                                              edited Dec 26 '17 at 20:27









                                                                              Nae

                                                                              5,58731136




                                                                              5,58731136










                                                                              answered Apr 15 '09 at 6:18









                                                                              jottos

                                                                              8,60092526




                                                                              8,60092526























                                                                                  4














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



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





                                                                                  share|improve this answer




























                                                                                    4














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



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





                                                                                    share|improve this answer


























                                                                                      4












                                                                                      4








                                                                                      4






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



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





                                                                                      share|improve this answer














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



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






                                                                                      share|improve this answer














                                                                                      share|improve this answer



                                                                                      share|improve this answer








                                                                                      edited Dec 27 '17 at 0:06









                                                                                      Nae

                                                                                      5,58731136




                                                                                      5,58731136










                                                                                      answered Jan 20 '17 at 10:02









                                                                                      Vikash Singh

                                                                                      444210




                                                                                      444210























                                                                                          3














                                                                                          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.






                                                                                          share|improve this answer























                                                                                          • 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
                                                                                            Dec 17 '15 at 14:24












                                                                                          • Now it's clear?
                                                                                            – Rax Wunter
                                                                                            Dec 17 '15 at 14:28










                                                                                          • It's related exactly to the mentioned issue: how to iterate safely without closure problems
                                                                                            – Rax Wunter
                                                                                            Dec 17 '15 at 14:31










                                                                                          • Now it doesn't seem significantly different from the accepted answer.
                                                                                            – Quentin
                                                                                            Dec 17 '15 at 14:31










                                                                                          • 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
                                                                                            Dec 17 '15 at 14:34


















                                                                                          3














                                                                                          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.






                                                                                          share|improve this answer























                                                                                          • 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
                                                                                            Dec 17 '15 at 14:24












                                                                                          • Now it's clear?
                                                                                            – Rax Wunter
                                                                                            Dec 17 '15 at 14:28










                                                                                          • It's related exactly to the mentioned issue: how to iterate safely without closure problems
                                                                                            – Rax Wunter
                                                                                            Dec 17 '15 at 14:31










                                                                                          • Now it doesn't seem significantly different from the accepted answer.
                                                                                            – Quentin
                                                                                            Dec 17 '15 at 14:31










                                                                                          • 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
                                                                                            Dec 17 '15 at 14:34
















                                                                                          3












                                                                                          3








                                                                                          3






                                                                                          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.






                                                                                          share|improve this answer














                                                                                          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.







                                                                                          share|improve this answer














                                                                                          share|improve this answer



                                                                                          share|improve this answer








                                                                                          edited Dec 17 '15 at 15:14









                                                                                          Ram

                                                                                          2,57993151




                                                                                          2,57993151










                                                                                          answered Dec 17 '15 at 14:14









                                                                                          Rax Wunter

                                                                                          1,53011523




                                                                                          1,53011523












                                                                                          • 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
                                                                                            Dec 17 '15 at 14:24












                                                                                          • Now it's clear?
                                                                                            – Rax Wunter
                                                                                            Dec 17 '15 at 14:28










                                                                                          • It's related exactly to the mentioned issue: how to iterate safely without closure problems
                                                                                            – Rax Wunter
                                                                                            Dec 17 '15 at 14:31










                                                                                          • Now it doesn't seem significantly different from the accepted answer.
                                                                                            – Quentin
                                                                                            Dec 17 '15 at 14:31










                                                                                          • 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
                                                                                            Dec 17 '15 at 14:34




















                                                                                          • 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
                                                                                            Dec 17 '15 at 14:24












                                                                                          • Now it's clear?
                                                                                            – Rax Wunter
                                                                                            Dec 17 '15 at 14:28










                                                                                          • It's related exactly to the mentioned issue: how to iterate safely without closure problems
                                                                                            – Rax Wunter
                                                                                            Dec 17 '15 at 14:31










                                                                                          • Now it doesn't seem significantly different from the accepted answer.
                                                                                            – Quentin
                                                                                            Dec 17 '15 at 14:31










                                                                                          • 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
                                                                                            Dec 17 '15 at 14:34


















                                                                                          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
                                                                                          Dec 17 '15 at 14:24






                                                                                          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
                                                                                          Dec 17 '15 at 14:24














                                                                                          Now it's clear?
                                                                                          – Rax Wunter
                                                                                          Dec 17 '15 at 14:28




                                                                                          Now it's clear?
                                                                                          – Rax Wunter
                                                                                          Dec 17 '15 at 14:28












                                                                                          It's related exactly to the mentioned issue: how to iterate safely without closure problems
                                                                                          – Rax Wunter
                                                                                          Dec 17 '15 at 14:31




                                                                                          It's related exactly to the mentioned issue: how to iterate safely without closure problems
                                                                                          – Rax Wunter
                                                                                          Dec 17 '15 at 14:31












                                                                                          Now it doesn't seem significantly different from the accepted answer.
                                                                                          – Quentin
                                                                                          Dec 17 '15 at 14:31




                                                                                          Now it doesn't seem significantly different from the accepted answer.
                                                                                          – Quentin
                                                                                          Dec 17 '15 at 14:31












                                                                                          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
                                                                                          Dec 17 '15 at 14:34






                                                                                          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
                                                                                          Dec 17 '15 at 14:34













                                                                                          3














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





                                                                                          share|improve this answer


























                                                                                            3














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





                                                                                            share|improve this answer
























                                                                                              3












                                                                                              3








                                                                                              3






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





                                                                                              share|improve this answer












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






                                                                                              share|improve this answer












                                                                                              share|improve this answer



                                                                                              share|improve this answer










                                                                                              answered Jul 13 at 8:02









                                                                                              ashish yadav

                                                                                              747713




                                                                                              747713























                                                                                                  2














                                                                                                  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 :)






                                                                                                  share|improve this answer



















                                                                                                  • 1




                                                                                                    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
                                                                                                    Jun 18 '15 at 18:21






                                                                                                  • 1




                                                                                                    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
                                                                                                    Oct 27 '15 at 4:07






                                                                                                  • 1




                                                                                                    @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
                                                                                                    Oct 27 '15 at 10:17
















                                                                                                  2














                                                                                                  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 :)






                                                                                                  share|improve this answer



















                                                                                                  • 1




                                                                                                    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
                                                                                                    Jun 18 '15 at 18:21






                                                                                                  • 1




                                                                                                    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
                                                                                                    Oct 27 '15 at 4:07






                                                                                                  • 1




                                                                                                    @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
                                                                                                    Oct 27 '15 at 10:17














                                                                                                  2












                                                                                                  2








                                                                                                  2






                                                                                                  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 :)






                                                                                                  share|improve this answer














                                                                                                  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 :)







                                                                                                  share|improve this answer














                                                                                                  share|improve this answer



                                                                                                  share|improve this answer








                                                                                                  edited Oct 27 '15 at 10:15

























                                                                                                  answered Jun 17 '15 at 12:02









                                                                                                  Rune FS

                                                                                                  18.3k64787




                                                                                                  18.3k64787








                                                                                                  • 1




                                                                                                    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
                                                                                                    Jun 18 '15 at 18:21






                                                                                                  • 1




                                                                                                    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
                                                                                                    Oct 27 '15 at 4:07






                                                                                                  • 1




                                                                                                    @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
                                                                                                    Oct 27 '15 at 10:17














                                                                                                  • 1




                                                                                                    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
                                                                                                    Jun 18 '15 at 18:21






                                                                                                  • 1




                                                                                                    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
                                                                                                    Oct 27 '15 at 4:07






                                                                                                  • 1




                                                                                                    @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
                                                                                                    Oct 27 '15 at 10:17








                                                                                                  1




                                                                                                  1




                                                                                                  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
                                                                                                  Jun 18 '15 at 18:21




                                                                                                  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
                                                                                                  Jun 18 '15 at 18:21




                                                                                                  1




                                                                                                  1




                                                                                                  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
                                                                                                  Oct 27 '15 at 4:07




                                                                                                  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
                                                                                                  Oct 27 '15 at 4:07




                                                                                                  1




                                                                                                  1




                                                                                                  @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
                                                                                                  Oct 27 '15 at 10:17




                                                                                                  @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
                                                                                                  Oct 27 '15 at 10:17











                                                                                                  2














                                                                                                  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.






                                                                                                  share|improve this answer




























                                                                                                    2














                                                                                                    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.






                                                                                                    share|improve this answer


























                                                                                                      2












                                                                                                      2








                                                                                                      2






                                                                                                      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.






                                                                                                      share|improve this answer














                                                                                                      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.






                                                                                                      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
                                                                                                      }





                                                                                                      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
                                                                                                      }






                                                                                                      share|improve this answer














                                                                                                      share|improve this answer



                                                                                                      share|improve this answer








                                                                                                      edited Aug 28 '17 at 16:37







                                                                                                      user7110739

















                                                                                                      answered May 5 '16 at 11:48









                                                                                                      pixel 67

                                                                                                      747617




                                                                                                      747617























                                                                                                          2














                                                                                                          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 the browser.



                                                                                                          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 the performance gain in different browsers.






                                                                                                          share|improve this answer























                                                                                                          • @TinyGiant The example with function being returned is still currying optimised for performance. I wouldn't jump on arrow functions bandwagon like all the JavaScript bloggers. They look cool and clean but promote writing functions inline instead of using predefined functions. This can be a non-obvious trap in hot places. Another problem is that they are not just syntactic sugar because they are executing unnecessary bindings thus creating wrapping closures.
                                                                                                            – Pawel
                                                                                                            Dec 27 '17 at 1:52










                                                                                                          • Warning to future readers: This answer inaccurately applies the term Currying. "Currying is when you break down a function that takes multiple arguments into a series of functions that take part of the arguments.". This code does nothing of the sort. All you've done here is take the code from the accepted answer, move some things around, change the style and naming a bit, then call it currying, which it categorically is not.
                                                                                                            – Tiny Giant
                                                                                                            Dec 27 '17 at 2:36
















                                                                                                          2














                                                                                                          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 the browser.



                                                                                                          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 the performance gain in different browsers.






                                                                                                          share|improve this answer























                                                                                                          • @TinyGiant The example with function being returned is still currying optimised for performance. I wouldn't jump on arrow functions bandwagon like all the JavaScript bloggers. They look cool and clean but promote writing functions inline instead of using predefined functions. This can be a non-obvious trap in hot places. Another problem is that they are not just syntactic sugar because they are executing unnecessary bindings thus creating wrapping closures.
                                                                                                            – Pawel
                                                                                                            Dec 27 '17 at 1:52










                                                                                                          • Warning to future readers: This answer inaccurately applies the term Currying. "Currying is when you break down a function that takes multiple arguments into a series of functions that take part of the arguments.". This code does nothing of the sort. All you've done here is take the code from the accepted answer, move some things around, change the style and naming a bit, then call it currying, which it categorically is not.
                                                                                                            – Tiny Giant
                                                                                                            Dec 27 '17 at 2:36














                                                                                                          2












                                                                                                          2








                                                                                                          2






                                                                                                          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 the browser.



                                                                                                          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 the performance gain in different browsers.






                                                                                                          share|improve this answer














                                                                                                          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 the browser.



                                                                                                          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 the performance gain in different browsers.







                                                                                                          share|improve this answer














                                                                                                          share|improve this answer



                                                                                                          share|improve this answer








                                                                                                          edited Dec 26 '17 at 21:21









                                                                                                          Nae

                                                                                                          5,58731136




                                                                                                          5,58731136










                                                                                                          answered Feb 28 '17 at 15:09









                                                                                                          Pawel

                                                                                                          5,62633442




                                                                                                          5,62633442












                                                                                                          • @TinyGiant The example with function being returned is still currying optimised for performance. I wouldn't jump on arrow functions bandwagon like all the JavaScript bloggers. They look cool and clean but promote writing functions inline instead of using predefined functions. This can be a non-obvious trap in hot places. Another problem is that they are not just syntactic sugar because they are executing unnecessary bindings thus creating wrapping closures.
                                                                                                            – Pawel
                                                                                                            Dec 27 '17 at 1:52










                                                                                                          • Warning to future readers: This answer inaccurately applies the term Currying. "Currying is when you break down a function that takes multiple arguments into a series of functions that take part of the arguments.". This code does nothing of the sort. All you've done here is take the code from the accepted answer, move some things around, change the style and naming a bit, then call it currying, which it categorically is not.
                                                                                                            – Tiny Giant
                                                                                                            Dec 27 '17 at 2:36


















                                                                                                          • @TinyGiant The example with function being returned is still currying optimised for performance. I wouldn't jump on arrow functions bandwagon like all the JavaScript bloggers. They look cool and clean but promote writing functions inline instead of using predefined functions. This can be a non-obvious trap in hot places. Another problem is that they are not just syntactic sugar because they are executing unnecessary bindings thus creating wrapping closures.
                                                                                                            – Pawel
                                                                                                            Dec 27 '17 at 1:52










                                                                                                          • Warning to future readers: This answer inaccurately applies the term Currying. "Currying is when you break down a function that takes multiple arguments into a series of functions that take part of the arguments.". This code does nothing of the sort. All you've done here is take the code from the accepted answer, move some things around, change the style and naming a bit, then call it currying, which it categorically is not.
                                                                                                            – Tiny Giant
                                                                                                            Dec 27 '17 at 2:36
















                                                                                                          @TinyGiant The example with function being returned is still currying optimised for performance. I wouldn't jump on arrow functions bandwagon like all the JavaScript bloggers. They look cool and clean but promote writing functions inline instead of using predefined functions. This can be a non-obvious trap in hot places. Another problem is that they are not just syntactic sugar because they are executing unnecessary bindings thus creating wrapping closures.
                                                                                                          – Pawel
                                                                                                          Dec 27 '17 at 1:52




                                                                                                          @TinyGiant The example with function being returned is still currying optimised for performance. I wouldn't jump on arrow functions bandwagon like all the JavaScript bloggers. They look cool and clean but promote writing functions inline instead of using predefined functions. This can be a non-obvious trap in hot places. Another problem is that they are not just syntactic sugar because they are executing unnecessary bindings thus creating wrapping closures.
                                                                                                          – Pawel
                                                                                                          Dec 27 '17 at 1:52












                                                                                                          Warning to future readers: This answer inaccurately applies the term Currying. "Currying is when you break down a function that takes multiple arguments into a series of functions that take part of the arguments.". This code does nothing of the sort. All you've done here is take the code from the accepted answer, move some things around, change the style and naming a bit, then call it currying, which it categorically is not.
                                                                                                          – Tiny Giant
                                                                                                          Dec 27 '17 at 2:36




                                                                                                          Warning to future readers: This answer inaccurately applies the term Currying. "Currying is when you break down a function that takes multiple arguments into a series of functions that take part of the arguments.". This code does nothing of the sort. All you've done here is take the code from the accepted answer, move some things around, change the style and naming a bit, then call it currying, which it categorically is not.
                                                                                                          – Tiny Giant
                                                                                                          Dec 27 '17 at 2:36











                                                                                                          2














                                                                                                          Your 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 the first loop is created with the condition of 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 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 the 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 the value of i in each iteration.



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






                                                                                                          share|improve this answer




























                                                                                                            2














                                                                                                            Your 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 the first loop is created with the condition of 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 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 the 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 the value of i in each iteration.



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






                                                                                                            share|improve this answer


























                                                                                                              2












                                                                                                              2








                                                                                                              2






                                                                                                              Your 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 the first loop is created with the condition of 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 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 the 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 the value of i in each iteration.



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






                                                                                                              share|improve this answer














                                                                                                              Your 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 the first loop is created with the condition of 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 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 the 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 the value of i in each iteration.



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







                                                                                                              share|improve this answer














                                                                                                              share|improve this answer



                                                                                                              share|improve this answer








                                                                                                              edited Dec 26 '17 at 22:53









                                                                                                              Nae

                                                                                                              5,58731136




                                                                                                              5,58731136










                                                                                                              answered Nov 4 '16 at 8:58









                                                                                                              Buksy

                                                                                                              4,91643857




                                                                                                              4,91643857























                                                                                                                  1














                                                                                                                  COUNTER BEING A PRIMITIVE



                                                                                                                  Let's 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 the callback function accesses the value based on the 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 the 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 what's 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, the value of the loop index will not be preserved. This is to show that the values of an 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





                                                                                                                  share|improve this answer




























                                                                                                                    1














                                                                                                                    COUNTER BEING A PRIMITIVE



                                                                                                                    Let's 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 the callback function accesses the value based on the 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 the 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 what's 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, the value of the loop index will not be preserved. This is to show that the values of an 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





                                                                                                                    share|improve this answer


























                                                                                                                      1












                                                                                                                      1








                                                                                                                      1






                                                                                                                      COUNTER BEING A PRIMITIVE



                                                                                                                      Let's 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 the callback function accesses the value based on the 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 the 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 what's 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, the value of the loop index will not be preserved. This is to show that the values of an 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





                                                                                                                      share|improve this answer














                                                                                                                      COUNTER BEING A PRIMITIVE



                                                                                                                      Let's 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 the callback function accesses the value based on the 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 the 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 what's 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, the value of the loop index will not be preserved. This is to show that the values of an 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






                                                                                                                      share|improve this answer














                                                                                                                      share|improve this answer



                                                                                                                      share|improve this answer








                                                                                                                      edited Dec 27 '17 at 0:01









                                                                                                                      Nae

                                                                                                                      5,58731136




                                                                                                                      5,58731136










                                                                                                                      answered Jul 17 '17 at 10:10









                                                                                                                      jsbisht

                                                                                                                      3,86053142




                                                                                                                      3,86053142






















                                                                                                                          1 2
                                                                                                                          next




                                                                                                                          protected by Josh Crozier May 11 '14 at 3:11



                                                                                                                          Thank you for your interest in this question.
                                                                                                                          Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).



                                                                                                                          Would you like to answer one of these unanswered questions instead?



                                                                                                                          這個網誌中的熱門文章

                                                                                                                          Xamarin.form Move up view when keyboard appear

                                                                                                                          Post-Redirect-Get with Spring WebFlux and Thymeleaf

                                                                                                                          Anylogic : not able to use stopDelay()