简体   繁体   中英

javascript anonymous function scope behavior

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.

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

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

** EDITED **

Your variable i inside your loop equals 10 at the time you call mc() 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM