3

以下のクロージャーの例に注目してください。

<script>
  function foo() {
    var x = 1;
    function bar() {
      var y = 2;
      alert(x + y);
    }
    return bar;
  }

   var dummy = foo(); // Assign variable binding "dummy" to a reference of the "bar" function.
   dummy(); // When entering the "bar" function code, will it go through the execution context creation phase?
</script>

ダミー変数バインディング ("bar" 関数コードを実行する) を呼び出すとき、新しい実行コンテキストが作成されますか? ECMAScript 仕様では、関数コードを入力したときに何が起こるかが指定されていますが、これは関数/クロージャーへの参照であるため、実行コンテキストの作成/バインディング フェーズ全体を再度実行する必要があるかどうかはわかりませんでした。

4

2 に答える 2

2

良い質問。何が起こっているか見てみましょう:

dummy()関数呼び出しです(11.2.3)

手順 8 を参照してください。「func で [[Call]] 内部メソッドを呼び出し、thisValue を this 値として指定し、リスト argList を引数値として指定した結果を返します。」を参照してください。

そうdummy.[[Call]]呼ばれます。13.2.1 ( ) に移行します[[Call]]

funcCtx を、F の [[FormalParameters]] 内部プロパティの値、渡された引数 List args、および 10.4.3 で説明されている this 値を使用して、関数コードの新しい実行コンテキストを確立した結果とする。

10.4.3dummy()で説明されているように、実際には新しい実行コンテキストを作成します

の関数コードが実行されたので、 NewDeclarativeEnvironmentdummyは 10.4.3 パスのステップ #5 に従って作成されます。dummy.[[Scope]]

dummyは への単なる参照でbarあり、 も同様dummy.[[Scope]]ですbar.[[Scope]]。Andbar.[[Scope]]は実行された瞬間foo(1 行前) に定義されており、( を含む) 内の関数宣言ごとに自然に関数が作成されますbar

bar.[[Scope]][global environment]本質的にはand [foo VE](Variable Environment)からなるチェーンです。そのため、実行時に独自の VE を作成し、foo の VE をアウターとして使用します。スコープ チェーンが で構成されるようになり[global environment]->[foo VE]->[bar VE]ました。

xvar の VE でy見つかり、bar の VE で見つかり、アラートが引数として正常に受信3されます:)

しかし、元の質問に答えるために、はい、「関数コードの入力」は次の場合に発生します

(function(){ ... })();

そしての場合

f();

どちらも基本的に関数の [[Call]] を呼び出すためです。1 つ目はCallExpressionが後にFunctionExpression続くArgumentsであるのに対し、2 つ目はCallExpressionが後にIdentifier続くArgumentsです。

どちらも、実行される内部 [[Call]] メソッドを持つ関数オブジェクトに解決されます。

于 2013-03-01T04:07:33.520 に答える
0

スコープチェーンはあなたがここで見ているものだと思います:

http://www.amazon.com/JavaScript-Definitive-Guide-Activate-Guides/dp/0596805527/ref=sr_1_2?ie=UTF8&qid=1362066219&sr=8-2&keywords=javascript (3.10.3)から

関数が呼び出されるたびに、そのローカル変数を格納するための新しいオブジェクトが作成され、その新しいオブジェクトが格納されたスコープ チェーンに追加されて、その関数呼び出しのスコープを表す新しい、より長いチェーンが作成されます。

あなたの質問についてはい、それは再び実行コンテキスト全体を通過します。そうでなければ、どのように bar() から別の関数を返すことができますか

function bar() {
      var y = 2;
      alert(x + y);

return function() {alert('hello');}
    }
于 2013-02-28T15:46:53.097 に答える