
JavaScriptデバイスについて多くの記事が書かれています。 まず、
「JavaScript。The kernel」です。 ドミトリーソシュニコフ 、
リチャードコーンフォードによる記事の翻訳、および
ドミトリーフランクによる投稿 。 しかし、技術を十分に把握するには、主要な情報源に目を向けることをお勧めします。 この場合、
ECMA-262標準
ECMAScript言語仕様に準拠します。 この投稿は、標準の調査を開始するための簡単な方法だと思います。 リンクをたどり、仕様書を読み、独自の図を作成することをお勧めします。
JavaScriptクロージャーの仕組み
主なECMAScript構造は、
実行コンテキスト 、
語彙環境 、および
環境レコードです。 それらは次のように接続されます。

VariableEnvironmentに加えて、 実行コンテキストにはLexicalEnvironmentもあります。違いの詳細については、 ECMAScript 5の仕様(LexicalEnvironmentとVariableEnvironment)を参照してください 。
ThisBindingについては、記事の次のパートで説明します。
環境レコードには、変数の値が格納されます。
var a = 1
を宣言すると、現在の
レコードに {a:1}が表示されます。
字句環境では 、
レコードのほかに、
外部フィールドもあります。
外部は、たとえば、ネストされた関数の場合の外部
レキシカル環境を指します。
変数の検索
は、現在のコンテキストの
VariableEnvironmentで始まります。 この名前の変数が
レコード内に見つからない場合
、 外部環境でチェーンによって検索されます 。
プログラムが起動すると
、グローバルコンテキストと環境が作成されます。
レコードとして、
グローバルオブジェクトが使用されます。

インタープリターが
functionキーワードを検出すると
、 FunctionObjectを作成します。 現在の
レキシカル環境への参照は、作成された
FunctionObjectの scopeプロパティに書き込まれます。
表記
function f(){}
、表記
var f = function(){}
function f(){}
ほぼ同等です。ただし、最初の場合は、
function f()
を含むブロックに入ると
FunctionObjectが作成され、2番目は特定の行を実行するときに作成されます。

関数が呼び出されるたび
に、新しいコンテキスト 、 環境 、およびレコードが作成されます。 コンテキストはスタックにプッシュされ、関数を終了すると破棄されます。 作成された
環境の 外側に 、呼び出された
FunctionObjectの スコープ が書き込まれます。 関数がグローバルコンテキストで宣言された場合、
outerは
グローバル環境を指し
ます 。

ここで、ある関数が別の関数を返すときの閉包を検討します。
var x = 1; function f() { var x = 2; function g() { return x; } return g; } f()();
関数
fが呼び出されると、
function g
FunctionObjectと同様に、
fの コンテキストと
環境 が作成されます。
スコープは、
VariableEnvironmentから現在の
環境への参照を書き込みます。
fを終了する
と、コンテキストは破棄されますが、返される
FunctionObjectからのリンクがあるため、
環境は残ります。
fから返された関数
g が呼び出されると、
gのコンテキストと
環境 が作成されます。 新しい
環境の
外側は、呼び出された
FunctionObjectから
スコープを書き込みます。 変数
xの検索は、現在の
VariableEnvironmentで始まり、次に
outerまで続きます。 その結果、値
x = 2
が返されます。
記事の次の部分では 、ECMAScriptの観点から
これがどのように機能するかを調べます。