JavaScript で関数が自分自身を呼び出す場合、スコープ チェーンでどのように解決されますか?
function myFunc(){
myFunc()
}
私はそれが悪いコードであり、永久に実行されることを知っています.
JavaScript で関数が自分自身を呼び出す場合、スコープ チェーンでどのように解決されますか?
function myFunc(){
myFunc()
}
私はそれが悪いコードであり、永久に実行されることを知っています.
関数宣言(上記のような)では、関数内で、関数の名前がスコープ内にあります。宣言された実行コンテキストの変数バインディング オブジェクトに追加されます。これについては、セクション 10.4.3およびセクション 10.5の乱文で説明します。仕様の。
たとえば、次のように考えてください。
function foo() {
function bar() {
}
}
を呼び出すと、呼び出しfoo
の実行コンテキストが作成されます。そのコンテキストには、変数バインディング オブジェクトが関連付けられています (詳細は省略します)。これは、その呼び出しの "スコープ" と大まかに考えることができます。内のステップバイステップ コードfoo
が実行される前に発生することの 1 つは、その中のすべての関数宣言が評価され、それらの関数の名前が への呼び出しのコンテキストの変数バインディング オブジェクトに追加されることfoo
です。(これは、foo
の引数名とローカル変数が格納される場所でもあります。) はそのコンテキストをbar
閉じるため、その名前を与えるものを含むバインディングにアクセスできます。
への呼び出しではなく、グローバル コンテキストを使用して、グローバル コードが最初に入力されたときに、同じことが (事実上) 発生しますfoo
。
私の質問は、それがどのように解決されるかです
JavaScript のスコープはマトリョーシカと考えることができます。JavaScript エンジンが識別子に遭遇すると (bar
上記の例のように)、最も内側の「スコープ」(変数バインディング オブジェクト) を調べて、その識別子のエントリがあるかどうかを確認します。ある場合は、それを使用します。そうでない場合は、含まれているスコープを調べて、それがあるかどうかを確認し、グローバル スコープに到達するまで繰り返します。この「スコープチェーン」のどの時点でも識別子が解決されず、そこから値を読み取ろうとすると、ReferenceError
. (値を設定しようとすると、暗黙的なグローバルが作成されます — 私の記事The Horror of Implicit Globals を参照してください — または、ReferenceError
厳密モードの場合。)
この解決策は、セクション 10.3.1、10.2.2.1などでカバーされていますが、非常に困難です。:-)