关于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
循环eg
for(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​​​