2011-02-17 73 views
3

对不起,关于标题 - 我找不出一个方法来描述它。当使用局部变量将匿名函数传递给命名函数时,Javascript中的作用域问题

这里的情景:

我有建立一个元素的功能:

buildSelect(id,cbFunc,...) 

里面buildSelect它这样做:

select.attachEvent('onchange',cbFunc); 

我也有去的数组:

var xs = ['x1','x2','x3'...]; 

鉴于所有这些,我有一些代码,这是否:

for(var i = 0; i < xs.length; i++) 
{ 
    buildSelect(blah,function(){ CallBack(xs[i],...) },...); 
} 

的问题是,当平变化得到这些选择的人开火。它正确地去回叫(),但第一个参数是不正确。例如,如果我改变第三个选择,我期望CallBack()被调用xs [2],而不是我得到一些不同的东西,如xs [3]或其他。

如果我修改稍微这样:

for(var i = 0; i < xs.length; i++) 
{ 
    var xm = xs[i]; 
    buildSelect(blah,function(){ CallBack(xm,...) },...); 
} 

我还是回调得到不正确的值()。有些东西告诉我这是范围/关闭相关,但我似乎无法弄清楚什么。

我只需要第一个选择为onchange调用CallBack,第一个参数为xs [0],第二个选择为xs [1]依此类推。我在这里做错了什么?

我应该说明xs是一个全局变量。

感谢

回答

4

你需要在自己的范围内围绕它关闭,以捕获​​值。

要做到这一点,需要一个单独的函数调用:

buildCallback(curr_xm) { 

     // this function will refer to the `xm` member passed in 
    return function(){ CallBack(curr_xm,...) },...); 
} 

for(var i = 0; i < xs.length; i++) 
{ 
    var xm = xs[ i ]; 
    buildSelect(blah,buildCallback(xm),...); 
} 

现在的回调是指​​是,你传递给buildCallback之一。

如果您有其他用途i需要被保留,您可以发送,而不是:

buildCallback(curr_i) { 


     // this function will refer to the `i` value passed in 
    return function(){ CallBack(xs[ curr_i ],...) },...); 
} 

for(var i = 0; i < xs.length; i++) 
{ 
    buildSelect(blah,buildCallback(i),...); 
} 
+0

谢谢!事实上,调用第二个函数有助于解决问题。 – encee 2011-02-17 04:06:18

+0

@ royrules22:不客气。我会注意到你也可以利用你现有的`buildSelect`函数。只需传入`i`或`xs [i]`,然后在那里创建处理程序。 `buildSelect(blah,xs [i],...);`这可能是最干净的。 – user113716 2011-02-17 04:09:06

4

是的,我想关闭将帮助:

for(var i = 0, l = xs.length; i < l; i++) 
{ 
    buildSelect(
     blah, 
     function(xm){ 
      return function(){ 
       CallBack(xm,...) 
      }; 
     }(xs[i]), 
     ... 
    ); 
} 

编辑:我也稍微优化了你的for循环。

编辑:我想我会添加一个解释。你正在做的是创建一个匿名函数,它接受一个参数(xm)并立即调用函数(紧接着括号)。这个匿名函数也必须返回你原来的函数作为buildSelect()的参数。

+0

对不起,我不得不接受另一个问题,但在这里接受这个虚拟复选标记!谢谢您的帮助! – encee 2011-02-17 04:08:57

4

问题确实与范围有关 - JavaScript只有函数范围,而不是范围范围或循环范围。变量i和​​只有一个实例,并且这些变量的值随循环的进行而变化。循环完成后,只剩下最后一个值。你的匿名函数本身捕获变量,而不是它们的值。

要捕获变量的实际值,则需要另一种功能,你可以捕捉局部变量:

function makeCallback(value) { 
    return function() { CallBack(value, ...) }; 
} 

makeCallback每次调用得到value变量的新实例,如果你抓住这个变量,你基本上捕获的值:

for(var i = 0; i < xs.length; i++) 
{ 
    buildSelect(blah,makeCallback(xs[i]),...); 
} 
相关问题