javascript匿名函数范围行为

时间:2011-02-06 04:31:27

标签: javascript node.js scope

我有一个遵循这种模式的代码:

a = "abcdefghijklmnopqrstuvwxyz";
m = {};

for(i=0;i<10;i++){
  m[a.charAt(i)] = function(){
      return i;
  };
}

console.log(m.c());

它返回10。

为什么这样做呢? 我怎么能让它返回相应的数字?

-------编辑-------

感谢您的回复。到目前为止提供的答案适用于上面的示例,但我忘了提到我需要传递一个回调函数。考虑到你的建议,我想出了这个:

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

结果同意我的直觉,认为它不起作用。有没有人对此有任何想法?

感谢您的帮助

由于您的帮助,我能够启动这个项目: https://github.com/sbussard/python-for-node

请随时继续按照您的意愿捐款。

3 个答案:

答案 0 :(得分:4)

循环中的笼子变量而不更改它们。

不期望的行为

> 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

<强>固定

>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

答案 1 :(得分:3)

该函数引用变量i。在执行函数时(在console.log()行),它会打印变量,此时变量值为10

要解决此问题,您需要在每次迭代中创建一个新变量,并为其分配当前值i。要在每次迭代中获得新的变量范围,可以使用其他函数:

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

答案 2 :(得分:0)

** 已编辑 **

在您调用i时,您的循环中的变量10等于m.c(),并且因为它在您的函数中使用,它会为每个“索引”返回10 。只需保存此变量的副本。例如:

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