2

私はクロージャーを理解しようとしており、W3Schools javascript チュートリアルを見ています。これはカウンターを作ることによって彼らが与える一例です。

<body>

<p>Counting with a local variable.</p>

<button type="button" onclick="myFunction()">Count!</button>

<p id="demo">0</p>

<script>
var add = (function () {
    var counter = 0;
     return function () {return counter += 1;}
})();

function myFunction(){
    document.getElementById("demo").innerHTML = add();
}
</script>

</body>

の説明 変数 add には、自己呼び出し関数の戻り値が割り当てられます。

自己呼び出し関数は 1 回だけ実行されます。カウンターをゼロ (0) に設定し、関数式を返します。

このように add は関数になります。「素晴らしい」部分は、親スコープのカウンターにアクセスできることです。

これは JavaScript クロージャーと呼ばれます。関数が「プライベート」変数を持つことを可能にします。

カウンターは無名関数のスコープによって保護されており、add 関数を使用してのみ変更できます。

クロージャーは、親関数が閉じられた後でも、親スコープにアクセスできる関数です。

説明は悪くありませんが、いくつか不明な点があります。自己呼び出し関数を使用するのが最適だったのはなぜですか? ネストされた匿名関数が自己呼び出し関数ではないのはなぜですか? また、カウンターが内部で既に返されているのに、なぜ無名関数全体を返す必要があるのでしょうか?

4

1 に答える 1

1

クロージャーの概念は、関数とそのコンテキストを持つものとして説明できます。コンテキストは、キャプチャされた変数を解決するために関数に接続された一種のストレージです (したがって、クロージャーと呼ばれますか?)。

サンプル コードが実行されると、次のようになります。

var add = (function () {
    var counter = 0; // This is promoted to the below's function context
    return function () {return counter += 1;}
})();

変数が無名関数コンテキストに昇格されるコンテキストを作成するとcounter、現在のスコープからその変数にアクセスできます。

この図は多かれ少なかれそれを説明しています:

JS 関数とコンテキスト

この場合、X と Y は関数コンテキストによってキャプチャされ、その関数のすべての実行に引き継がれます。

さて、これは単なるレキシカル環境の V8 実装です。

V8 を使用したクロージャの実装に関する Vyacheslav Egorov の優れた説明を参照してください:楽しみ (そして利益?) のために V8 クロージャをグロッキングする

于 2016-02-26T18:14:23.947 に答える