4

クライアント側アプリケーションの開発中に、クロージャの使用についての私の不完全な理解に関連していると私が信じるエラーに遭遇しました。私は自分のコードを次のように切り詰めました:


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: reference to undefined property "x"

このエラーが発生する理由と、fn1によって返されるクロージャ関数のローカルスコープで定義された変数にfn2がアクセスできない理由を知りたいのですが。

4

2 に答える 2

8

つまり、クロージャは、使用されている場所ではなく、宣言された場所に関連して親スコープにアクセスできます。

によって返される関数はfn1、その親関数(fn1それ自体)のスコープにアクセスできます。つまり、にアクセスできますarr。ただし、配列内の関数は、配列から返された関数内または関数内で定義された変数にアクセスできませんfn1。これらの関数(配列内)は別のスコープで宣言されているためです。

あなたがそのコードで解決しようとしている実際の問題に関して、私がそれを正しく理解したかどうかはわかりません。特定の数にいくつかの関数を適用しようとしているようです。20その数(あなたの例では)が定数であり、パラメーターではない理由がわかりません。これがそのための私の提案された解決策です(クロージャなし!):

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​​​
于 2012-06-17T18:55:45.023 に答える
3

エラーが行にあると思われますx+=20

var x = 20によって返される無名関数のスコープ内にのみ存在しfn1ます。 x+=20以前に評価するfn1のでx、その時点では存在しません。

于 2012-06-17T18:58:52.413 に答える