var foo = "hello"; var c =(function a(){function b(){var bar = "world"; alert(foo + bar); return bar;} return b;})()()(); alert(foo + c);この例では、Hello Worldを2回ポップアップします。
1。閉鎖とは何ですか?
「公式」の説明は次のとおりです。いわゆる「閉鎖」とは、これらの変数に縛られた多くの変数と環境がある式(通常は関数)を指します。したがって、これらの変数も式の一部です。
彼があまりにも学問的に説明したので、この文を直接理解できる人はほとんどいないと思います。 JavaScriptに閉鎖を作成する方法を使用して、クロージャーが何であるかを説明したいと思います。これは、クロージャー作成プロセスをスキップすることで閉鎖の定義を直接理解することが非常に困難だからです。次のコードを見てください。
function a(){var i = 0; function b(){alert(++ i);} return b;} var c = a(); c();このコードには2つの特性があります。
1。関数Bは関数内の内側にネストされています。
2。関数a戻り機能b。
このようにして、var c = a()を実行した後、変数Cは実際に関数bを指します。 c()を実行すると、ウィンドウがポップアップしてiの値を表示します(初めては1です)。このコードは実際に閉鎖を作成します。なぜ?変数c外部関数aは、関数内関数a、つまり、:
関数Aの内部関数Bが変数外部関数Aによって参照されると、閉鎖が作成されます。
閉鎖が何であるかわからないので、まだ閉鎖を理解していないと思います。以下を調べてみましょう。
2。閉鎖の機能は何ですか?
要するに、閉鎖の機能は、Aが実行されて返された後、閉鎖により、aの内部関数Bの実行がaの変数に依存するために、aが占めるリソースを回復しないJavaScriptのガベージコレクションメカニズムがa。これは、閉鎖の役割の非常に簡単な説明であり、これは専門的でも厳密でもありませんが、大まかにそうであることを意味します。閉鎖を理解するには、段階的なプロセスが必要です。
上記の例では、関数aが返された後、iは常に存在するため、c()が実行されるたびに、iは1を追加した後にアラートされた値です。
次に、別の状況を想像しましょう。 aが関数bではない場合、状況は完全に異なります。 Aが実行された後、BはAの外の世界に戻さず、Aによってのみ参照されるため、AはBによってのみ参照されるため、機能は互いに参照されますが、外の世界(外の世界で参照)が妨害されることはありません。 (JavaScriptのごみ収集メカニズムは、後で詳細に紹介されます)
3.閉鎖における顕微鏡の世界
閉鎖と機能Aとネストされた関数Bの関係をより深く理解したい場合は、関数の実行環境(excutionオブジェクト)、範囲(スコープ)、スコープチェーンなど、いくつかの他の概念を導入する必要があります。これらの概念を説明するための例として、機能Aのプロセスを定義から実行まで取得します。
1.関数Aを定義する場合、JSインタープリターは、aを定義するときにAが位置する「環境」に機能のスコープチェーンAを設定します。 Aがグローバル関数の場合、スコープチェーンにはウィンドウオブジェクトのみがあります。
2。関数Aが実行されると、Aは対応する実行環境(excutionコンテキスト)に入ります。
3。実行環境を作成するプロセスでは、Aは最初にスコープ属性を追加します。つまり、Aのスコープとその値はステップ1のスコープチェーンです。つまり、A.Scope = aのスコープチェーンです。
4.実行環境は、アクティブオブジェクト(コールオブジェクト)を作成します。アクティブオブジェクトは属性を持つオブジェクトでもありますが、プロトタイプはなく、JavaScriptコードを介して直接アクセスすることはできません。アクティブオブジェクトを作成した後、アクティブオブジェクトをaのスコープチェーンの上部に追加します。この時点で、Aのスコープチェーンには、Aのアクティブオブジェクトとウィンドウオブジェクトの2つのオブジェクトが含まれています。
5.次のステップは、関数aを呼び出すときに渡されるパラメーターを保存するアクティブオブジェクトに引数属性を追加することです。
6.最後に、関数aのすべての正式なパラメーターと内部関数bへの参照を、aのアクティブオブジェクトに追加します。このステップでは、関数Bの定義が完了するため、ステップ3と同様に、関数BのスコープチェーンがBで定義された環境に設定されます。つまり、Aの範囲です。
この時点で、関数A全体が定義から実行まで完了します。この時点で、aは関数bへの参照をcに戻し、関数bのスコープチェーンには関数aのアクティブオブジェクトへの参照が含まれています。つまり、bはaで定義されているすべての変数と関数にアクセスできます。関数BはCによって参照され、関数Bは関数Aに依存しているため、関数AはGCが返された後にリサイクルされません。
関数Bが実行されると、上記と同じです。したがって、実行中のbのスコープチェーンには、下の図に示すように、bのアクティブオブジェクト、Aのアクティブオブジェクト、およびウィンドウオブジェクトが3つのオブジェクトが含まれています。
図に示すように、関数Bの変数にアクセスするとき、検索順序は最初に独自のアクティブオブジェクトを検索することであり、それが存在する場合、それは戻ります。存在しない場合は、機能Aのアクティブなオブジェクトを検索し続け、発見されるまで順番に検索します。スコープチェーン全体で見つからない場合、未定義が返されます。関数Bにプロトタイププロトタイプオブジェクトがある場合、独自のアクティブオブジェクトを検索した後、最初に独自のプロトタイプオブジェクトを探してから検索を続けます。これは、JavaScriptの可変検索メカニズムです。
4。閉鎖のアプリケーションシナリオ
1。関数内の変数のセキュリティを保護します。最初の例を例として、関数Aでは、関数Bでのみアクセスできますが、他のチャネルを介してアクセスすることはできないため、iのセキュリティを保護します。
2。メモリに変数を維持します。まだ前と同じように、閉鎖のために、私は機能Aに常にメモリに存在するため、c()が実行されるたびに、1が追加されます。
上記の2つのポイントは、閉鎖の最も基本的なアプリケーションシナリオであり、多くの古典的なケースがこれに由来しています。
5。JavaScriptのガベージコレクションメカニズム
JavaScriptでは、オブジェクトが参照されなくなった場合、オブジェクトはGCによってリサイクルされます。 2つのオブジェクトが互いに参照され、第三者によって参照されなくなった場合、互いに参照される2つのオブジェクトがリサイクルされます。関数AはBによって参照されるため、BはAの外側のCによって参照されます。そのため、機能Aは実行後にリサイクルされません。
上記の記事は、閉鎖メカニズムが私があなたと共有するすべてのコンテンツであることを包括的に理解しています。参照を提供できることを願っています。wulin.comをもっとサポートできることを願っています。