0

JavaScript で関数が自分自身を呼び出す場合、スコープ チェーンでどのように解決されますか?

function myFunc(){
    myFunc()
}

私はそれが悪いコードであり、永久に実行されることを知っています.

4

1 に答える 1

5

関数宣言(上記のような)では、関数内で、関数の名前がスコープ内にあります。宣言された実行コンテキストの変数バインディング オブジェクトに追加されます。これについては、セクション 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.110.2.2.1などでカバーされていますが、非常に困難です。:-)

于 2013-10-01T08:58:51.257 に答える