Reputation: 9346
I have this sample code:
function(){
var events = [];
var pages = ["a", "b", "c"];
for(var pageIndex in pages){
var pageName = pages[pageIndex];
var e = function(){
console.info(pageName);
};
events.push(e);
}
for(var eventIndex in events){
console.info("index: " + eventIndex);
events[eventIndex]();
}
}
Output:
index: 0
c
index: 1
c
index: 2
c
Desired output:
index: 0
a
index: 1
b
index: 2
c
Is there a standard practice for this?
Upvotes: 0
Views: 46
Reputation: 6701
Welcome to closures in javascript, you need to wrap the function in an IIFE or immediately invoked function expression which creates a closure and saves the state in its scope:
(function(){
var events = [];
var pages = ["a", "b", "c"];
for(var pageIndex in pages){
var pageName = pages[pageIndex];
var e = (function(pageName){
return function() {console.info(pageName);};
}(pageName));
events.push(e);
}
for(var eventIndex in events){
console.info("index: " + eventIndex);
events[eventIndex]();
}
}());
Copy and paste it into the console debugger to test...
Upvotes: 1
Reputation: 208475
Each e
function that you create is a closure that accesses the external variable pageName
from the enclosing code. The pageName
that it will see is the value at the time the function is run. So at the end of your loop pageName
is "c"
, so that is what all of the functions will use when they are executed.
You can fix this by wrapping your function in the following way, which will essentially bind the current value of pageName
to the function you create:
function(){
var events = [];
var pages = ["a", "b", "c"];
for(var pageIndex in pages){
var pageName = pages[pageIndex];
var e = (function(data) {
return function() {
console.info(data);
};
})(pageName);
events.push(e);
}
for(var eventIndex in events){
console.info("index: " + eventIndex);
events[eventIndex]();
}
}
Upvotes: 1
Reputation: 9346
I found the answer here. I need to wrap my function in another function. How nifty.
Template.index.test = function(){
var events = [];
var pages = ["a", "b", "c"];
for(var pageIndex in pages){
var pageName = pages[pageIndex];
var e = function(pageName) {
return function(){
console.info(pageName);
};
}(pageName);
events.push(e);
}
for(var eventIndex in events){
console.info("index: " + eventIndex);
events[eventIndex]();
}
}
Upvotes: 0