私は(理論的には)クロージャがJSでどのように実装されているかを理解しようとしていますが、混乱することが1つあり、答えを見つけることができませんでした。
JSのクロージャは、アクティベーションオブジェクトのチェーンを使用します。各関数呼び出しには1つあり、それはその親のアクティベーションオブジェクトを指します。これはを指します その 親のアクティベーションオブジェクトなど。
私が正しく理解していれば、この場合の「親」は、子関数があった関数呼び出しです。 定義された に。
しかし、子供はどのようにして親を知っていますか?アクティベーションオブジェクト?子関数は、それを定義した関数呼び出しの外部であっても、プログラム内のどこからでも呼び出すことができます。関数が定義されたときに、親のアクティベーションオブジェクトが関数オブジェクト自体に何らかの形で格納されていますか?すべての関数呼び出しは、どういうわけか、親のアクティベーションオブジェクトをそれ自体の関数オブジェクトから取得しますか?それは私が考えることができる唯一の説明ですが、それを確認することはできませんでした。
また、アクティベーションオブジェクトを検査する方法はありますか(方法と同じように) __proto__
検査できます)?
回答:
回答№1は1少なくともECMAの用語では、あなたが説明していることは、 語彙環境.
語彙環境は、 環境記録 そして 外部の語彙環境へのおそらくnull参照.
そしてそれぞれ function
を持っていると定義されています 内部 [[Scope]]
プロパティ (参照:表9)、これはそのような環境の1つを参照しています。
Function.[[Scope]] ->
LexicalEnvironment.Outer ->
LexicalEnvironment
# etc.
ザ .Outer
このプロパティは単なる推測ですが、エンジンは外部環境を参照しますが、その値は現在のコンテキストの環境の値です。 [[Scope]]
周囲の function
またはの プログラム 自体。
とき function
が呼び出されて変数を参照すると、エンジンは「スコープチェーン参照されている名前が見つかるか、環境が不足してスローされるまで、環境とそのレコードの ReferenceError
.
また、アクティベーションオブジェクトを検査する方法はありますか(方法と同じように)
__proto__
検査できます)?
現在、言語自体では不可能です。内部プロパティには、JavaScript内で直接アクセスすることはできません。 [[Scope]]
プロパティには、のように公開するものがありません。 [[Prototype]]
財産は持っています Object.getPrototypeOf()
または __proto__
.
ただし、Bergiが述べたように、JavaScriptデバッガーを使用するとスコープチェーンを検査できる場合があります。例えば、 ChromeのWebツールの「スコープ変数」の下:
スクリプトが一時停止している間、右側のサイドバーに現在のコールスタックとスコープ内の変数が表示されます。