サンプルコード:
var xxxVar1 = 1;
var external = function(){
var xxxVar2 = 2;
var results = [];
for(var i = 0; i {
var inner = function(){
var xxxVar3 = 3;
return xxxVar3 xxxVar2 xxxVar1 i;
}
結果 .push(inner);
}
結果を返します;
}
var xxxVar1 = 100;
var xxxVar2 = 200;
var xxxVar3 = 300;
var results = inner();
results[0 ]();
results[1]();
results[2]();
実行結果
何が起こったのでしょうか? 多くの人は上記の例の実行結果を知っているかもしれませんが、なぜこの結果になるのかは私も含めて誰もが理解しているわけではありません。名詞 説明 アクティブ オブジェクト: 関数呼び出しの開始時に、JavaScript インタプリタは関数本体内のすべてのローカル変数 (var 形式で宣言された変数) を収集し、これらのローカル変数を「アクティブ オブジェクト」と呼ばれるオブジェクトに格納します。変数は最初は未定義です。
コード例
var fun = function (){
alert(name);
var name = 'Duan Guangwei';
}
この関数 (fun()) を実行するとき、関数本体は現在のアクティブなオブジェクトは [{ 名前: 未定義 }] であるため、fun() の実行結果は次のようになります:
関数の [scope] 属性: 各関数には、定義時 (関数インスタンスの生成時) に [scope] 属性が割り当てられ、現在の「スコープ チェーン」を指します。開発者はこの属性にアクセスできません。JavaScript のみがアクセスできます。
スコープ チェーン: 関数が呼び出されるとき、JavaScript エンジンはこの呼び出しのスコープ チェーンを維持します。このスコープ チェーンは、関数の [scope] が指すスコープ チェーンに、関数が呼び出されたときにアクティブなオブジェクトを加えたものです。 [アクティブオブジェクト、関数定義時のスコープチェーン] のような形式で記述します。
コード例
var a = 1 ;
//ステップ 1: [ { a: 1, 外側: 未定義 } ]
var external = function(){
//ステップ 3: [ { b: 未定義, 内側: 未定義} ,{ a: 1, inner: function } ]
var b = 2;
var inner = function(){
//ステップ 5: [ {}, { b: 2, inner: function } ,{ a: 1, 外側: 関数 }
]
return inner();
}
//ステップ 2: [ { a: 1, 外側: 関数 } ]
external();
スコープ チェーン ルール ルール 1
JavaScript は通常、特定のホストで実行されます。各ホストは「グローバル オブジェクト」または「グローバル アクティブ オブジェクト」を提供します。このグローバル オブジェクトは、すべてのスコープ チェーンのルート ノードです。 ルール 2
「値操作」 (alert(xxxVar) など) のルールは、スコープ チェーンに沿って「xxxVar」という名前の変数を検索し、最初に見つかった値を返し、見つからない場合は例外をスローします (ReferenceError) : xxxVar が定義されていません)。 ルール 3
「代入操作」 (xxxVar = 'Duan Guangwei' など) のルールは、スコープ チェーンに沿って "xxxVar" という名前の変数を検索し、見つからない場合は、最初に見つかった値を上書きします。グローバルオブジェクトに。 注: 「クロージャ」の概念は「スコープ チェーン」を通じて実装されますが、C# はコンパイラを通じて実装され、.NET はそれをサポートしません。