首頁  >  文章  >  web前端  >  JavaScript變數物件其二:VO在不同的執行上下文中

JavaScript變數物件其二:VO在不同的執行上下文中

高洛峰
高洛峰原創
2016-11-28 14:56:481395瀏覽

不同執行上下文中的變數物件

對於所有類型的執行上下文來說,變數物件的一些操作(如變數初始化)和行為都是共通的。從這個角度來看,把變數物件當作抽象的基本事物來理解更為容易。同樣在函數上下文中也定義和變數物件相關的額外內容。

抽象变量对象VO (变量初始化过程的一般行为)
  ║
  ╠══> 全局上下文变量对象GlobalContextVO
  ║        (VO === this === global)
  ║
  ╚══> 函数上下文变量对象FunctionContextVO
           (VO === AO, 并且添加了<arguments>和<formal parameters>)

我們來詳細看一下:

全域上下文中的變數物件

首先,我們要給全域物件一個明確的定義:

全域物件(Global object) 是在進入任何執行上下文之前就已經建立了的對象。這個物件只存在一份,它的屬性在程式中任何地方都可以訪問,全域物件的生命週期終止於程式退出那一刻。

全域物件初始建立階段將Math、String、Date、parseInt作為自身屬性,等屬性初始化,同樣也可以有額外建立的其它物件作為屬性(其可以指向到全域物件本身)。例如,在DOM中,全域物件的window屬性就可以引用全域物件本身(當然,並不是所有的具體實作都是這樣):

global = {
  Math: <...>,
  String: <...>
  ...
  ...
  window: global //引用自身
};

當存取全域物件的屬性時通常會忽略掉前綴,這是因為全域物件是不能透過名稱直接存取的。不過我們還是可以透過全域上下文的this來存取全域對象,同樣也可以遞迴引用自身。例如,DOM中的window。綜上所述,程式碼可以簡寫為:

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(&#39;test&#39;);
  
alert(a); // 直接访问,在VO(globalContext)里找到:"test"
  
alert(window[&#39;a&#39;]); // 间接通过global访问:global === VO(globalContext): "test"
alert(a === this.a); // true
  
var aKey = &#39;a&#39;;
alert(window[aKey]); // 间接通过动态属性名称访问:"test"

函數上下文中的變數物件

在函數執行上下文中,VO是不能直接存取的,此時由活動物件(activation object,縮寫為AO)扮演VO的角色。

VO(functionContext) === AO;

活動物件是在進入函數上下文時刻被建立的,它透過函數的arguments屬性初始化。 arguments屬性的值是Arguments物件:

AO = {
  arguments: <ArgO>
};

Arguments物件是活動物件的屬性,它包含以下屬性:

callee — 指向目前函數的參考

length — 真正傳遞的參數個數

字串類型的整數) 屬性的值就是函數的參數值(按參數列表從左到右排列)。 properties-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瀏覽器裡有一個bug — 即使沒有傳遞參數z,z和arguments[2]仍然是共享的。

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn