異なる実行コンテキストの変数オブジェクト
変数オブジェクトの一部の操作 (変数の初期化など) と動作は、すべてのタイプの実行コンテキストに共通です。この観点から見ると、変数オブジェクトは抽象的な基本的なものとして理解するのが容易です。変数オブジェクトに関連する追加のコンテンツも関数コンテキストで定義されます。
抽象变量对象VO (变量初始化过程的一般行为) ║ ╠══> 全局上下文变量对象GlobalContextVO ║ (VO === this === global) ║ ╚══> 函数上下文变量对象FunctionContextVO (VO === AO, 并且添加了<arguments>和<formal parameters>)
詳しく見てみましょう:
グローバル コンテキスト内の変数オブジェクト
まず、グローバル オブジェクトに明確な定義を与える必要があります:
グローバル オブジェクト (グローバル オブジェクト) は、実行コンテキスト オブジェクトに入る前に作成されます。 。このオブジェクトのコピーは 1 つだけ存在し、そのプロパティにはプログラム内のどこからでもアクセスできます。グローバル オブジェクトのライフサイクルは、プログラムが終了した時点で終了します。
グローバル オブジェクトの最初の作成フェーズでは、Math、String、Date、parseInt が独自の属性として使用され、他の属性も初期化されます (グローバル オブジェクトを指すことができる) 追加で作成された他のオブジェクトを持つこともできます。自体)。たとえば、DOM では、グローバル オブジェクトの window プロパティはグローバル オブジェクト自体を参照できます (もちろん、すべての特定の実装がこのようになるわけではありません):
global = { Math: <...>, String: <...> ... ... window: global //引用自身 };
グローバル オブジェクトのプロパティにアクセスするときのプレフィックスは、これは、グローバル オブジェクトには名前で直接アクセスできないためです。ただし、グローバル コンテキストの this を通じてグローバル オブジェクトにアクセスすることはできますし、それ自体を再帰的に参照することもできます。たとえば、DOM のウィンドウです。要約すると、コードは次のように省略できます:
String(10); // 就是global.String(10); // 带有前缀 window.a = 10; // === global.window.a = 10 === global.a = 10; this.b = 20; // global.b = 20;
それで、グローバル コンテキストの変数オブジェクトに戻ります。ここで、変数オブジェクトはグローバル オブジェクトそのものです:
VO(globalContext) === global;
を理解することが非常に必要です。上記の結論は、この原則に基づいて、対応関係がグローバル コンテキストで宣言されている場合にのみ、グローバル オブジェクトのプロパティを通じて間接的にアクセスできます (たとえば、変数名を事前に知らなくても)。
var a = new String('test'); alert(a); // 直接访问,在VO(globalContext)里找到:"test" alert(window['a']); // 间接通过global访问:global === VO(globalContext): "test" alert(a === this.a); // true var aKey = 'a'; alert(window[aKey]); // 间接通过动态属性名称访问:"test"
関数コンテキストの変数オブジェクト
関数実行コンテキストでは、VO に直接アクセスすることはできません。このとき、アクティベーション オブジェクト (AO と略されます) が VO の役割を果たします。
VO(functionContext) === AO;
アクティブ オブジェクトは関数コンテキストに入るときに作成され、関数の argument 属性を通じて初期化されます。 argument 属性の値は Arguments オブジェクトです:
AO = { arguments: <ArgO> };
Arguments オブジェクトはアクティブ オブジェクトのプロパティであり、次のプロパティが含まれます:
callee — 現在の関数への参照
length — 実際のパラメーターの数渡された
properties-indexes (文字列型の整数) 属性の値は、関数のパラメーター値です (パラメーター リストの左から右に配置されています)。 property-indexes 内の要素の数は、arguments.length と等しくなります。properties-indexes の値は、実際に渡されるパラメータと共有されます。
例:
function foo(x, y, z) { // 声明的函数参数数量arguments (x, y, z) alert(foo.length); // 3 // 真正传进来的参数个数(only x, y) alert(arguments.length); // 2 // 参数的callee是函数自身 alert(arguments.callee === foo); // true // 参数共享 alert(x === arguments[0]); // true alert(x); // 10 arguments[0] = 20; alert(x); // 20 x = 30; alert(arguments[0]); // 30 // 不过,没有传进来的参数z,和参数的第3个索引值是不共享的 z = 40; alert(arguments[2]); // undefined arguments[2] = 50; alert(z); // 40 } foo(10, 20);
この例のコードには、現在のバージョンの Google Chrome にバグがあります。パラメーター z が渡されない場合でも、z と argument[2] は依然として共有されます。