エンクロージャ


以下の内容は学院課程と「モダンjavascript Deep Dive:李雄莫沢」の読書と総括である。

エンクロージャ


なぜロッカーが必要ですか?


関数が値(ステータス)を変更する必要があり、その値がグローバルコードにある場合、その値はすべての人、すべてのコードにアクセスできるため、本当に必要な場合、必要な結果(値)が得られない場合があります.プログラミングでは、エラーはプログラムが機能しないだけでなく、開発者が何気なく発生した場合も含まれているので、エラーが発生します.したがって、ステータスを安全に非表示にし、特定の関数のみのステータス変更を許可し、キャビネットを使用して作成する必要があります.

エンクロージャとは?


「モジュールは、関数とその関数と宣言されたLexical環境の組合せです。」

MDNでは、モジュール定義は以下の通りである.もしそうであれば,モジュールを正しく理解するためにはLexicalScopeと関数を正しく理解しなければならないことを意味する.

では、Lexical環境とは何でしょうか。


Scopeでは少し言及していますが、JavaScriptの関数は、どこで定義された関数に基づいて関数を決定する親Scopeを表し、これをLexical Scoperと呼びます.
また,関数を学習する際に,関数の有用性を述べたように,関数を事前に定義すれば,必要に応じて繰り返し呼び出すことができる.もしそうであれば、関数の定義点と関数の実行点が異なる場合がありますが、上記のLexical Scopeを実現するためには、関数定義の瞬間の親Scopeを覚えておく必要があります.そのため、関数は自分の定義した環境、すなわち親Scopeの参照を自分の内部スロットに格納します.
const x = 1;

function foo() {
  const x = 10;
  bar();
}

function bar() {
  console.log(x);
}

foo(); // ?
bar(); // ?
上のコードの答えは両方とも1です.これはjavascriptの関数が関数を定義する際に親スキャンを決定しているため,bar関数をどこで呼び出してもbar関数コード内部で決定できるxの値は1である.
まとめると、LexicalScorp環境の外部LexicalScorp環境への参照に格納される参照値、すなわち親Scorpの参照は、関数定義が評価されたときの関数定義の位置によって決定されます.これがLexicalScorpです.

では、ロッカーは何ですか。


ネスト(内部)関数が外部関数よりも長く保持されている場合、外部関数の外部でネスト関数を呼び出しても、Closerと呼ばれる外部関数の領域変数にアクセスできます.

これはどうしたんですか。


通常、スキャンが終了すると、スキャン外部は終了したスキャン内部の識別子を参照できないため、この場合は特殊な場合となる.
const x = 1;

// ①
function outer() {
  const x = 10;
  const inner = function () { console.log(x); }; // ②
  return inner;
}

// outer 함수를 호출하면 중첩 함수 inner를 반환한다.
// 그리고 outer 함수의 실행 컨텍스트는 실행 컨텍스트 스택에서 팝되어 제거된다.
const innerFunc = outer(); // ③
innerFunc(); // ④ 10
上記のコードをよく見ると、innerFuncはouter関数を実行する値を割り当てているため、内部関数であると考えられます.内層関数を呼び出すと、outer関数のスキャンが終了する可能性があります.呼び出し関数の位置はグローバルスキャンであるため、内層関数が参照する必要があるx変数は、終了したouter関数のスキャンではなく、グローバルスキャンにおけるx変数の値1です.ただし、javascriptの関数は、関数を呼び出す瞬間ではなく、関数を定義する瞬間のスキャンを位相スキャンとして記録するため、inner関数は、スキャンチェーンに基づいてouter関数のスキャン中のx変数の値10をコンソールウィンドウに撮影する.
内部関数が外部関数より長く保持されているが、外部関数の識別子が参照されていない場合、外部関数の識別子はゴミ収集器によってメモリから解放されます.参照されていない識別子をメモリに保持することは、メモリ領域を浪費することです.
サンプルコードソース モダンjavascript Deep Dive:伊雄モゼ