變數物件VO與活動物件AO

2022-05-09 07:57:08 字數 3599 閱讀 7111

變數物件vo

變數物件vo是與執行上下文相關的特殊物件,用來儲存上下文的函式宣告,函式形參和變數。在global全域性上下文中,變數物件也是全域性物件自身,在函式上下文中,變數物件被表示為活動物件ao。

變數物件vo儲存上下文中宣告的以下內容 

;test(30);

// 全域性上下文的變數物件

vo(globalcontext) = ;

// test函式上下文的變數物件

vo(test functioncontext) = ;

變數物件vo分類

全域性上下文的變數物件vo,函式上下文的變數物件vo。

//全域性上下文的變數物件vo就是全域性物件globalcontextvo

vo(globalcontext) === global;

(vo === this === global)
函式上下文變數物件functioncontextvo  

(vo === ao, 並且新增了(形參類陣列)和(形參的值))
活動變數ao

在函式執行上下文中,vo是不能直接訪問的,此時由活動物件ao扮演vo的角色

當函式被呼叫後,這個特殊的活動物件就被建立了。它包含普通引數與特殊引數物件(具有索引屬性的引數對映表)。活動物件ao在函式上下文中作為變數物件vo使用。

arguments物件是活動物件的乙個屬性,它包括如下屬性:

callee — 指向當前函式的引用

length — 真正傳遞的引數個數

properties-indexes (字串型別的整數) 屬性的值就是函式的引數值(按引數列表從左到右排列)。 

properties-indexes內部元素的個數等於arguments.length. properties-indexes 的值和實際傳遞進來的引數之間是共享的。

function

foo(x, y, z)

foo(10, 20);

view code

處理上下文**的2個階段

進入執行上下文和執行**

進入執行上下文: 

變數是進入上下文階段放入vo中,也就是變數宣告提公升並且變數宣告順序上是在函式宣告和形參宣告後

//變數宣告在順序上跟在函式宣告和形式引數宣告之後,而且在這個進入上下文階段,變數宣告不會干擾vo中已經存在的同名函式宣告或形式引數宣告

alert(x); // function

var x = 10;

alert(x); // 10

x = 20;

function x() {};

alert(x); // 20

alert(x); // 20

var x = 10;

alert(x); // 10

x = 20;

function b(x) {};

alert(x); // 20

function test(a, b) 

var e = function _e() {};

(function x() {});

}test(10); // call

當進入帶有引數10的test函式上下文時,ao表現為如下:

//ao裡並不包含函式「x」。這是因為「x」 是乙個函式表示式(functionexpression, 縮寫為 fe) 而不是函式宣告,函式表示式不會影響vo

ao(test) = ;

//函式表示式不在ao中

console.log(x) // x is not defined

(function x() {});

特例

var x =10;

function foo()

var barfe = function () ;

var barfn = function('alert(x); alert(y);');

barfd(); // 10, 20

barfe(); // 10, 20

barfn(); // 10, "y" is not defined

} foo();

我們看到,通過function函式建構函式(function constructor)建立的函式「bar」,是不能訪問變數「y」的。但這並不意味著函式「barfn」沒有[[scope]]屬性(否則它不能訪問到變數「x」)。問題在於通過函建構函式建立的函式的[[scope]]屬性總是唯一的全域性物件(如果再全域性設定y值才可以訪問)。考慮到這一點,如通過這種函式建立除全域性之外的最上層的上下文閉包是不可能的。

執行上下文:

a:定義:

每次當控制器轉到ecmascript可執行**的時候,即會進入到乙個執行上下文。執行上下文(簡稱-ec)是ecma-262標準裡的乙個抽象概念,用於同可執行**(executable code)概念進行區分。

活動的執行上下文組在邏輯上組成乙個堆疊。堆疊底部永遠都是全域性上下文(global context),而頂部就是當前(活動的)執行上下文。堆疊在ec型別進入和退出上下文的時候被修改(進棧或出棧)。

b:若我們定義執行上下文堆疊是乙個陣列:

ecstack = ;

//globalcontext始終在堆疊底部,其餘的functioncontext按啟用順序被壓入,結束時被彈出

ecstack = [

globalcontext

];ecstack = [  functionaacontext,//函式a內部函式a可執行** 

functionacontext,//函式a可執行**(不包含內部函式**,只能對其宣告,就像在全域性中只能對函式a宣告一樣,需要內部函式啟用時,建立   globalcontext 出新的執行上下文環境,才能執行相應的**)      呼叫結束後出棧  ];;

ps:每次進入function (即使function被遞迴呼叫或作為建構函式) 的時候或者內建的eval函式工作的時候,當前的執行上下文都會被壓入堆疊;

全域性執行上下文做了這些工作:

如果**段是函式體,那麼在此基礎上需要附加:

給執行上下文環境下乙個通俗的定義——在執行**之前,把將要用到的所有的變數都事先拿出來,有的直接賦值了,有的先用undefined占個空。

現在讓我們來串一下

1、全域性執行上下文

建立global.vo

2、全域性變數的賦值 | 呼叫函式()(啟用)

啟用函式後,會得到當前的ao,其中有內部函式的宣告、內部變數的宣告、形參

3、進入所啟用的函式的上下文

進行所在函式上的變數的賦值 各種運算 (作用域鏈包含全域性的vo,和當前執行上下文的ao)

4.a、若在函式中有內部函式呼叫(或自執行),重複3;

4.b  若返回乙個函式(或其引用),且該函式有對自由變數的引用-->形成閉包-->作用域鏈機制依然有效-->當前已壓入執行上下文堆疊的functioncontext不會出棧;-->回到2;

4.c  正常return或正常結束,functioncontext出棧;-->回到2;

5.所有**執行完畢,程式關閉,釋放記憶體。

VO變數物件

js原理 原型鏈 執行上下文 事件迴圈 棧 棧是類似於陣列的一種資料結構。物件引用 如果變數是乙個物件,實際上變數中存放的是物件的位址 執行上下文 某個函式或全域性 的執行環境,該環境中包含執行 需要的所有資訊。可以簡單的理解為 執行上下文是乙個物件,物件中包含了執行 需要的資訊。當執行乙個函式時,...

js 閉包,作用域鏈,活動物件,變數物件

什麼是閉包 簡單的來講,就是乙個函式,乙個有權訪問另外乙個函式作用域內的變數的函式,常見的建立閉包的方式就是在乙個函式內部建立另外乙個函式 問題又來了,什麼是函式作用域 先要介紹一下什麼是執行環境 環境 執行環境定義了變數或者函式有權訪問的其他資料,決定了它們各自的行為,每乙個環境都有乙個與之關聯的...

引用變數與物件

各種oo語言中採用不同方式例項化 建立 物件。在c 中,當宣告乙個使用者自定義型別變數,如 student y 的時候,並沒有在記憶體中真的建立物件,而只是宣告了studnet型別的引用變數y。該引用變數可能會指向乙個student物件,但目前還沒有 或者說,它的值為null,null是c 關鍵字,...