关于javascript闭包的困惑
在开发客户端应用程序时,我遇到了一个错误,我认为这与我不完全理解闭包的使用有关。我已将代码缩减为以下内容:关于javascript闭包的困惑,javascript,closures,Javascript,Closures,在开发客户端应用程序时,我遇到了一个错误,我认为这与我不完全理解闭包的使用有关。我已将代码缩减为以下内容: var fn1 = function(arr){ return function(val){ var idx; var x = 20; for (idx in arr) { arr[idx](); } } } var fn2 = fn1([function(){ x+= 20; alert(x); }]) 现在
var fn1 = function(arr){
return function(val){
var idx;
var x = 20;
for (idx in arr) {
arr[idx]();
}
}
}
var fn2 = fn1([function(){
x+= 20;
alert(x);
}])
现在执行时:
fn2()
我收到一个错误:
ReferenceError:引用未定义的属性“x”
我想知道为什么会出现这个错误,为什么fn2不能访问fn1返回的闭包函数的局部作用域中定义的变量?简而言之:闭包可以访问与声明它们的位置相关的父作用域,而不是使用它们的位置
fn1
返回的函数可以访问其父函数的范围(fn1
本身),即它可以访问arr
。但是数组中的函数无法访问fn1
或从中返回的函数中定义的变量,因为这些函数(数组中)是在不同的范围内声明的
关于您试图用该代码解决的实际问题,我不确定我是否正确理解了它。看起来您正在尝试对某个数字应用某些函数。我不明白为什么这个数字(20
在你的例子中)是常数而不是参数。下面是我为此提出的解决方案(没有闭包!):
var applyArrayFunctions=函数(arr,x){
对于(var i=0;i我怀疑错误在x+=20行中
var x=20
仅存在于由fn1
返回的匿名函数的范围内。
x+=20
比fn1
先求值,所以x
在当时根本不存在。同样的解释也不需要在数组中使用fon,而实际问题的解决方案在代码方面会更好。谢谢你的证明。说得非常清楚。消除了我的误解。@Sarfraz我只是去掉了hasOwnP属性检查以使代码一致。不过谢谢你的提示。@Lorefnon:不,我的意思是你不应该在数组的循环中使用(它用于对象),使用简单的for
循环egfor(idx=0;idx
@Lorefnon:Simple:in
中的仅用于对象而不是数组。如果您对对象和数组之间的区别感到困惑,您也可以提出问题以获得帮助。
fn2()
var applyArrayFunctions = function(arr, x){
for(var i=0; i<arr.length; i++) {
x = arr[i](x);
}
return x;
}
var num = 2;
var fnArray = [
function(val){
return val + 20;
},
function(val){
return val * 2;
}
];
console.log(applyArrayFunctions(fnArray, num)); // logs 44