執(zhí)行上下文
當(dāng)ECMAScript 代碼執(zhí)行時(shí),它總是在一定的上下文中運(yùn)行,執(zhí)行上下文是一個(gè)有點(diǎn)抽象的實(shí)體,它有助于我們理解作用域和變量實(shí)例化如何工作的。對于三種類型的可執(zhí)行代碼,每個(gè)都有執(zhí)行的上下文。當(dāng)一個(gè)函數(shù)執(zhí)行時(shí),可以說控制進(jìn)入到函數(shù)代碼(Function code)的執(zhí)行上下文。全局代碼執(zhí)行時(shí),進(jìn)入到全局代碼(Global code)的執(zhí)行上下文。
正如你所見,執(zhí)行上下文邏輯上來自一個(gè)棧。首先可能是有自己作用域的全局代碼,代碼中可能調(diào)用一個(gè)函數(shù),它有自己的作用域,函數(shù)可以調(diào)用另外一個(gè)函數(shù),等等。即使函數(shù)遞歸地調(diào)用它自身,每一次調(diào)用都進(jìn)入一個(gè)新的執(zhí)行上下文。
激活對象/可變對象
每一個(gè)執(zhí)行上下文在其內(nèi)部都有一個(gè)所謂的可變對象。與執(zhí)行上下文類似,可變對象是一個(gè)抽象的實(shí)體,一個(gè)描述變量示例化的機(jī)制,F(xiàn)在,最有趣的是在源代碼中聲明的變量和函數(shù)被當(dāng)作這個(gè)可變對象的屬性被添加。
當(dāng)控制進(jìn)入全局代碼的執(zhí)行上下文時(shí),一個(gè)全局對象用作可變對象。這也正是為什么在全局范圍中聲明的變量或者函數(shù)變成了全局對象的屬性。
/* remember that `this` refers to global object when in global scope */
var GLOBAL_OBJECT = this ;
var foo = 1;
GLOBAL_OBJECT.foo; // 1
foo === GLOBAL_OBJECT.foo; // true
function bar(){}
typeof GLOBAL_OBJECT.bar; // "function"
GLOBAL_OBJECT.bar === bar; // true
Ok,全局變量變成了全局對象的屬性,但是,那些在函數(shù)代碼(Function code)中定義的局部變量又會如何呢?行為其實(shí)很相似:它成了可變對象的屬性。唯一的差別在于在函數(shù)代碼(Function code)中,可變對象不是全局對象,而是所謂的激活對象。每次函數(shù)代碼(Function code)進(jìn)入執(zhí)行作用域時(shí),激活對象即被創(chuàng)建。
不僅函數(shù)代碼(Function code)中的變量和函數(shù)成為激活對象的屬性,而且函數(shù)的每一個(gè)參數(shù)(與形參相對應(yīng)的名稱)和一個(gè)特定Arguments 對象(Arguments )也是。注意,激活對象是一種內(nèi)部機(jī)制,不會被程序代碼真正訪問到。
( function (foo){
var bar = 2;
function baz(){}
/*
In abstract terms,
Special `arguments` object becomes a property of containing function's Activation object:
ACTIVATION_OBJECT.arguments; // Arguments object
...as well as argument `foo`:
ACTIVATION_OBJECT.foo; // 1
...as well as variable `bar`:
ACTIVATION_OBJECT.bar; // 2
...as well as function declared locally:
typeof ACTIVATION_OBJECT.baz; // "function"
*/
})(1);
最后,在Eval 代碼(Eval code)中聲明的變量作為正在調(diào)用的上下文的可變對象的屬性被創(chuàng)建。Eval 代碼(Eval code)只使用它正在被調(diào)用的哪個(gè)執(zhí)行上下文的可變對象。
var GLOBAL_OBJECT = this ;
/* `foo` is created as a property of calling context Variable object,
which in this case is a Global object */
eval( 'var foo = 1;' );
GLOBAL_OBJECT.foo; // 1
( function (){
/* `bar` is created as a property of calling context Variable object,
which in this case is an Activation object of containing function */
eval( 'var bar = 1;' );
/*
In abstract terms,
ACTIVATION_OBJECT.bar; // 1
*/
})();
出處:
責(zé)任編輯:bluehearts
上一頁 理解delete [1] 下一頁 理解delete [3]
◎進(jìn)入論壇網(wǎng)頁制作、WEB標(biāo)準(zhǔn)化版塊參加討論,我還想發(fā)表評論。
|