Reputation: 8178
I have a code that kind of follows this pattern:
a = "abcdefghijklmnopqrstuvwxyz";
m = {};
for(i=0;i<10;i++){
m[a.charAt(i)] = function(){
return i;
};
}
console.log(m.c());
it returns 10.
WHY the heck does it do that? And how could I get it to return the corresponding number?
------- EDIT -------
Thank for your great responses. The answers that have been provided so far work for the above example, but I forgot to mention that I need to pass a callback function. Taking your advice into consideration I came up with this:
a = "abcdefghijklmnopqrstuvwxyz";
m = {};
f = function(i) {
return function(){
return i;
}
}
for(i=0;i<10;i++){
var eval('n') = "hi";
console.log(n);
m[a.charAt(i)] = function(fn){
fn(f(i));
};
}
m.c(function(a){console.log(a);});
and the outcome agreed with my intuition that it would not work. Does anyone have any ideas for this?
Thanks for your help
As a result of your help here I was able to start this project: https://github.com/sbussard/python-for-node
Please feel free to continue to contribute as you wish.
Upvotes: 2
Views: 1570
Reputation: 40770
Cage variables in a loop without changing them.
Non desired behaviour
> myFunctions = new Array()
[object Array]
for(var i = 0; i < 3; ++i) myFunctions[i] = function() { return i; }
> myFunctions[0]()
3
> myFunctions[1]()
3
> myFunctions[2]()
3
Fixed
>myFunctions = new Array()
[object Array]
function mkFunctionWithCagedValue(value) {
return function() {
return value;
};
}
> for(var i = 0; i < 3; ++i) myFunctions[i] = mkFunctionWithCagedValue(i)
[object Function]
> myFunctions[0]()
0
> myFunctions[1]()
1
> myFunctions[2]()
2
Upvotes: 4
Reputation: 53536
** EDITED **
Your variable i
inside your loop equals 10
at the time you call m.c()
and since it is used in your function, it returns 10
for each "index". Just save a copy of this variable. For example :
someFunction = function() {
alert(i); // will alert 10 because using i from the loop!
};
a = "abcdefghijklmnopqrstuvwxyz";
m = {};
for(i=0;i<10;i++){
m[a.charAt(i)] = (function(i, callback) {
// i is a local copy!
return function() {
callback(); // invoke callback function
return i;
};
})(i, someFunction);
}
console.log(m.c()); // would return 2
Upvotes: 0
Reputation: 229593
The function references the variable i
. At when the function is executed (at the console.log()
line), it prints the variable, which has a value of 10
at that time.
To work around this problem you need to create a new variable in each iteration that gets assigned the current value of i
. To get a new variable scope in each iteration you can use an additional function:
for(i=0;i<10;i++){
function use_copy() {
var icopy = i; # a new variable to hold the value of i
return (function(){
# original function, now using icopy
return icopy;
});
}
m[a.charAt(i)] = use_copy();
}
Upvotes: 3