関数をクリック ハンドラーに割り当てると、クロージャーが作成されます。
基本的に、関数をネストするとクロージャーが形成されます。内部関数は、親関数が既に実行された後でも、外側の囲み関数に存在する変数を参照できます。
クリック イベントが実行された時点で、ハンドラは変数が持っていた最後の値を参照しi
ます。これは、その変数がクロージャに格納されているためです。
お気づきのとおり、i
変数を引数として受け入れるためにクリック ハンドラー関数をラップし、別の関数を返す (基本的には別のクロージャーを作成する) ことで、期待どおりに動作します。
for ( var i = 0; i < 4; i++ ) {
var a = document.createElement( "a" );
a.onclick = (function(j) { // a closure is created
return function () {
alert(j);
}
}(i));
document.getElementById( "foo" ).appendChild( a );
}
反復して実際に 4 つの関数を作成すると、各関数i
は作成時の参照を格納し ( を渡すことによってi
)、この値は外側のクロージャに格納され、クリック イベントが発生すると内側の関数が実行されます。
次のスニペットを使用して、クロージャー (およびカリーの非常に基本的な概念) を説明します。単純な例を使用すると、概念を理解しやすくなると思います。
// a function that generates functions to add two numbers
function addGenerator (x) { // closure that stores the first number
return function (y){ // make the addition
return x + y;
};
}
var plusOne = addGenerator(1), // create two number adding functions
addFive = addGenerator(5);
alert(addFive(10)); // 15
alert(plusOne(10)); // 11