前端基礎(chǔ)(1):變量對象和執(zhí)行環(huán)境深入理解

背景

夯實基礎(chǔ)才是進(jìn)步的根源,基礎(chǔ)不牢地動山搖!!于是乎,結(jié)合《javascript高級程序設(shè)計》來點基礎(chǔ)的學(xué)習(xí)和理解。本文主要會有兩部分。rt??!

正文

1、執(zhí)行環(huán)境的理解

執(zhí)行環(huán)境(或者執(zhí)行上下文)(execution context 后面簡稱ec)定義了變量或者函數(shù)有權(quán)訪問的其他數(shù)據(jù),決定了他們各自的行為。如果不好理解的話,接著看后面。

全局執(zhí)行環(huán)境是最外圍的一個執(zhí)行環(huán)境,在web瀏覽器中,全局執(zhí)行環(huán)境被默認(rèn)為是指window對象。因此所有的全局變量和函數(shù)都是作為window對象的屬性和方法創(chuàng)建的。全局執(zhí)行環(huán)境直到應(yīng)用程序推出才會被銷毀(例如關(guān)閉網(wǎng)頁或者瀏覽器的時候)。

每個函數(shù)都有自己的執(zhí)行環(huán)境。當(dāng)執(zhí)行流進(jìn)入一個函數(shù)的時候,函數(shù)的環(huán)境就會被推入一個環(huán)境棧中,而在函數(shù)執(zhí)行之后,棧將其環(huán)境彈出。把控制權(quán)返回給之前的執(zhí)行環(huán)境了。執(zhí)行環(huán)境一般分為全局執(zhí)行環(huán)境和函數(shù)執(zhí)行環(huán)境。

這個時候應(yīng)該上代碼了(高程上的代碼)

var color = 'blue';
function changeColor() {    
    var anotherColor = 'red'; 
    function swapColors() {        
       var tempColor = anotherColor;       
           anotherColor = color;       
           color = tempColor;   
    }    
    swapColors();
}
changeColor();

來看看流程吧:

  1. 全局環(huán)境入棧


    image
    image
  2. 全局環(huán)境入棧之后,其中的可執(zhí)行代碼開始執(zhí)行,直到遇到了changeColor(),這一句激活函數(shù)changeColor創(chuàng)建它自己的執(zhí)行上下文,因此第二步就是changeColor的執(zhí)行上下文入棧。
    image
    image
  3. changeColor的環(huán)境入棧之后,js執(zhí)行引擎開始執(zhí)行其中的可執(zhí)行代碼,遇到swapColors()之后又激活了一個執(zhí)行上下文。因此第三步是swapColors的執(zhí)行上下文入棧。


    wechatimg1
    wechatimg1
  4. 在swapColors的可執(zhí)行代碼中,再沒有遇到其他能生成執(zhí)行環(huán)境的情況,所以在swapColors順利執(zhí)行完畢后,swapColors的環(huán)境從棧中彈出
  5. swapColors環(huán)境彈出后繼續(xù)changeColor的執(zhí)行,發(fā)現(xiàn)沒有可以執(zhí)行的了。然后就彈出。
  6. 最后只剩下全局環(huán)境了。這個是要只有關(guān)閉當(dāng)前網(wǎng)頁或者瀏覽器就能銷毀該環(huán)境。

總結(jié)

  1. 所有變量都存在于一個執(zhí)行環(huán)境中。
  2. 全局環(huán)境只能訪問全局環(huán)境中的變量和函數(shù),不能訪問局部環(huán)境中的任何數(shù)據(jù)。3. 執(zhí)行環(huán)境有全局執(zhí)行環(huán)境和函數(shù)執(zhí)行環(huán)境之分。
  3. js單線程,是同步執(zhí)行的,只有棧頂?shù)沫h(huán)境處于執(zhí)行中,其他環(huán)境需要等待。

2、變量對象的理解

上面我們講到了執(zhí)行環(huán)境,環(huán)境中的變量和函數(shù)都是保存在什么地方的呢?好了,不賣關(guān)子了。
每個執(zhí)行環(huán)境都有一個與該環(huán)境相關(guān)聯(lián)的變量對象(variable object)。環(huán)境中定義的所有變量和函數(shù)都是保存在這個對象中的。雖然我們編寫的代碼沒有辦法直接訪問這個對象,但是js解析器在處理數(shù)據(jù)的時候會使用它。
執(zhí)行環(huán)境的生命周期:

wechatimg15
wechatimg15

變量對象的創(chuàng)建
image
image

上面就是變量對象的一個創(chuàng)建過程,這個過程的解釋:

  1. 建立arguments對象。檢查當(dāng)前上下文中的參數(shù),建立該對象下的屬性與屬性值。2. 檢查當(dāng)前上下文的函數(shù)聲明,也就是使用function關(guān)鍵字聲明的函數(shù)。在變量對象中以函數(shù)名建立一個屬性,屬性值為指向該函數(shù)所在內(nèi)存地址的引用。如果函數(shù)名的屬性已經(jīng)存在,那么該屬性將會被新的引用所覆蓋。
  2. 檢查當(dāng)前上下文中的變量聲明,每找到一個變量聲明,就在變量對象中以變量名建立一個屬性,屬性值為undefined。如果該變量名的屬性已經(jīng)存在,為了防止同名的函數(shù)被修改為undefined,則會直接跳過,原屬性值不會被修改。
    上面的代碼解釋:
function test(c, d) {
   console.log(d);    
   console.log(a);   
   console.log(bar());    
   console.log(c);        
   var a = 1;   
   function bar() {       
       return 2; 
   }
}
test(3,4);
//創(chuàng)建過程  EC = execution context
testEC = {    
  // 變量對象    
  VO: {},   
  // 作用于鏈   
  scopeChain: {},   
  // 確定this指向   
  this: {}
}
// VO = Variable Object,即變量對象
VO = {    
    arguments: {    
         c: undefined,
         d: undefined
    },  //注:在瀏覽器的展示中,函數(shù)的參數(shù)可能并不是放在arguments對象中,這里為了方便理解,我做了這樣的處理   
    bar: ‘函數(shù)引用’, // 表示foo的地址引用    
    a: undefined
}
// 執(zhí)行階段VO ->  AO  // 
Active ObjectAO = {    
    arguments: {    c: 3,    d: 4    },   
    bar: ‘函數(shù)引用’,    
    a: 1
}
// 實際執(zhí)行
function test(c, d) {
    // arguments = { c : 3, d : 4 };
    // 這樣理解方便點,理解arguments對象   
    function foo() {        return 2;    }   
    var a;   
    console.log(a);    
    console.log(foo());    
    a = 1;
}
test(3, 4);

就是在執(zhí)行環(huán)境在創(chuàng)建階段的時候所有的變量是不能被訪問的,只有在執(zhí)行階段的時候才能被訪問,因為此時的變量對象被轉(zhuǎn)換成了活動對象。


// 執(zhí)行階段VO ->  AO  // Active Object
AO = {    
    arguments: {...},    
    foo: '函數(shù)引用',
    a: 1
}

說到底變量對象和活動對象本質(zhì)上是一樣的,只是處于執(zhí)行環(huán)境的不同生命期。

最后全局環(huán)境的變量對象


windowEC = {
   VO: window,
   scopeChain: {},
   this: window
}

總結(jié)

  1. 活動對象和變量對象是執(zhí)行環(huán)境在不同生命期的不同叫法。

  2. function聲明會比var聲明優(yōu)先級更高一點。

  3. 未進(jìn)入執(zhí)行階段之前,變量對象中的屬性都不能訪問。

感謝

《javascript高級程序設(shè)計》

知乎上面的答案

波同學(xué)變量對象詳解

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容