0

javascript クロージャーに関する記事をフォローしています。

実行コンテキストの詳細を知ろうとして、私は驚くべき結果に出くわしました。

var globalVar = 'g';
var inner;
var outer = function() {
  var outerVar = 'o';
  inner = function() {
    var innerVar = 'i';
    console.log(innerVar, outerVar, globalVar);
  }
}

outer()
inner() // Q: What does this log out?

http://jsfiddle.net/6zvsh/

これは実際に出力しますi o g

私は見ると思っていましたi undefined g

これがプロセスの私の理解です。エラーを理解したい:

  1. innerグローバルオブジェクトのプロパティとして宣言され、値がに設定されますundefined
  2. outerが呼び出されます。
  3. outerスコープ チェーンにouterVarグローバル オブジェクトが含まれる実行コンテキストが作成されます。
  4. グローバル オブジェクトのプロパティの値にはinner、関数定義への参照が割り当てられます。
  5. 終了の実行コンテキストouter。(関連するスコープは削除されていますか? GC 用にマークされていますか?)
  6. innerが呼び出されます。
  7. innerVarスコープ チェーンにグローバル オブジェクトが含まれる実行コンテキストが作成されます。
  8. outerVar範囲内に見つかりません

outerVarが定義されている理由を誰か説明してもらえますか?

4

1 に答える 1

1

関数が作成されると、その周囲の実行コンテキストをスコープとして参照し、クロージャーを作成します。

それを見てみましょう:

1.innerグローバル オブジェクトのプロパティとして宣言され、値がundefined

1.5。関数が作成され、outerグローバル スコープがその親スコープとして参照されます。

2.outer呼び出されます。

3.outerスコープチェーンouterVarにグローバル オブジェクトが含まれる実行コンテキストが作成されます。

outer…新しい実行コンテキストのチェーン リンクは、 (1.5 で割り当てられた) グローバル スコープである の親スコープを参照するためです。outerVarこの新しい実行コンテキストの変数です。

4.innerグローバル オブジェクトのプロパティの値には、関数定義への参照が割り当てられます。

…そして、関数の親スコープは の実行コンテキストに設定されますouter

5. 終了の実行コンテキストouter(関連するスコープは削除されていますか? GC 用にマークされていますか?)

inner…しかし、まだ生きている関数の親スコープとしてまだ参照されているため(ガベージではありません)、ガベージコレクションされません。

6.inner呼び出されます。

7. スコープチェーンinnerVarにグローバル オブジェクトが含まれる実行コンテキストが作成されます。

新しい実行コンテキストには、inner親コンテキストへのスコープ チェーン リンクがあります。これは、outer呼び出し用に上記で作成された実行コンテキストです (グローバル スコープへのチェーン リンクがあります)。innerVarこの新しい実行コンテキストの変数です。

8.範囲内にouterVarありません

…鎖。

于 2014-04-26T20:02:08.977 に答える