将匿名函数传递给带有局部变量的命名函数时Javascript中的作用域问题
关于这个标题,我很抱歉,我想不出一个表达方式 以下是场景: 我有一个构建元素的函数:将匿名函数传递给带有局部变量的命名函数时Javascript中的作用域问题,javascript,scope,attachevent,Javascript,Scope,Attachevent,关于这个标题,我很抱歉,我想不出一个表达方式 以下是场景: 我有一个构建元素的函数: buildSelect(id,cbFunc,...) 在buildSelect中,它执行以下操作: select.attachEvent('onchange',cbFunc); for(var i = 0; i < xs.length; i++) { buildSelect(blah,function(){ CallBack(xs[i],...) },...); } 我还有一个数组: var
buildSelect(id,cbFunc,...)
在buildSelect中,它执行以下操作:
select.attachEvent('onchange',cbFunc);
for(var i = 0; i < xs.length; i++)
{
buildSelect(blah,function(){ CallBack(xs[i],...) },...);
}
我还有一个数组:
var xs = ['x1','x2','x3'...];
鉴于所有这些,我有一些代码可以做到这一点:
select.attachEvent('onchange',cbFunc);
for(var i = 0; i < xs.length; i++)
{
buildSelect(blah,function(){ CallBack(xs[i],...) },...);
}
for(变量i=0;i
问题是,当对其中一个选择触发onchange时,它会正确地转到CallBack(),但第一个参数不正确。例如,如果我更改了第三个select,我希望回调()可以用xs[2]调用,而得到一些变化的东西,比如xs[3]或其他东西
如果我将其稍微修改为:
for(var i = 0; i < xs.length; i++)
{
var xm = xs[i];
buildSelect(blah,function(){ CallBack(xm,...) },...);
}
for(变量i=0;i
我仍然在CallBack()中得到不正确的值。有些东西告诉我这与范围/闭包有关,但我似乎不知道是什么
我只想让第一个select调用callbackforonchange,第一个参数为xs[0],第二个select调用xs[1],依此类推。我在这里做错了什么
我应该澄清xs是一个全局变量
谢谢您需要通过在它自己的范围内关闭它来捕获
xm
值
为此,需要单独的函数调用:
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 ),...);
}
是的,我认为关闭将有助于:
for(var i = 0, l = xs.length; i < l; i++)
{
buildSelect(
blah,
function(xm){
return function(){
CallBack(xm,...)
};
}(xs[i]),
...
);
}
for(变量i=0,l=xs.length;i
编辑:我还稍微优化了for循环
编辑:我想我会添加一个解释。您要做的是创建一个匿名函数,它接受一个参数(xm),并直接调用该函数(后面有括号)。此匿名函数还必须将原始函数作为buildSelect()的参数返回。问题确实与作用域相关——JavaScript只有函数作用域,没有块作用域或循环作用域。变量
i
和xm
只有一个实例,这些变量的值随着循环的进行而变化。循环完成后,只剩下最后一个值。匿名函数捕获变量本身,而不是它们的值
要捕获变量的实际值,您需要另一个可以捕获局部变量的函数:
function makeCallback(value) {
return function() { CallBack(value, ...) };
}
每次调用makeCallback
都会获取value
变量的一个新实例,如果捕获该变量,则基本上捕获该值:
for(var i = 0; i < xs.length; i++)
{
buildSelect(blah,makeCallback(xs[i]),...);
}
for(变量i=0;i
显然有一个新的let
关键字可以满足您的需求:
for(var i = 0; i < xs.length; i++)
{
let xm = xs[i];
buildSelect(blah,function(){ CallBack(xm,...) },...);
}
for(变量i=0;i
谢谢!我不知道JS没有块作用域。好吧,直到。再次感谢!谢谢的确,调用第二个函数有助于解决问题。@royrules22:不客气。我要指出的是,您还可以利用现有的buildSelect
功能。只需传入i
或xs[i]
,然后在其中创建处理程序<代码>构建选择(blah,xs[i],…)代码>这可能是最干净的。对不起,我不得不接受另一个问题,但这里接受这个虚拟复选标记!谢谢你的帮助!