《JavaScript高級程序設計》總結(三)——執行上下文棧和變量對象

執行上下文棧

你們都知道js是單線程的,因此這就意味着它一次只能作一個件事情,而一個js的文件中必然會執行多個操做,好比全局代碼,函數代碼,每執行一次就會生成多個執行上下文,js中採用棧的方式來處理它,你們都知道棧的執行是先進的後出,所以全局的執行上下文永遠是最底層的,在程序執行完畢的時候出棧數組

咱們舉個栗子來模擬一下執行上下文棧的流程bash

<script>
          
          function EC(){
              let b = 1 
              console.log(b)
          }
          EC()

    </script>
複製代碼

1.首先咱們把執行上下文棧假設成一個數組,這樣比較好理解,當代碼還未執行時,執行上文棧是空的函數

ECStack = [];
複製代碼

2.當上述代碼剛進入script標籤後,就進入了一個全局的環境,此時的全局環境的執行上下文就會入棧,咱們用globalContext來表示全局的執行上下文ui

ECStack = [
    globalContext
 ]
複製代碼

3.咱們接着來看咱們的代碼,此時js遇到了以下代碼this

function EC(){
              let b = 1 
              console.log(b)
        }
複製代碼

此時編譯器遇到了函數,它會生成一個函數的執行上下文並壓入棧中,咱們用ECContext來表示該函數的執行上下文spa

//此時的ECStack中多了一個ECContext,而globalContext被壓到了棧底
 ECStack = [
    ECContext,
    globalContext
 ]
複製代碼

4.再接着看咱們的代碼,此時該執行函數EC了,此時EC的執行上下文內部會作一些處理,這個咱們後面會講到,如今咱們只關心執行上文棧是怎麼操做的線程

//當EC函數執行完後,在棧頂的ECContext會彈出,棧底的globalContext會到棧頂的位置,此時的ECStack
            ECStack = [
                globalContext
            ]
            
複製代碼

當該js被銷燬的時候,globalContext會彈出棧,ECStack被回收,至此一個完整的js就走完了指針

你們可能會有些疑問,頻頻提到的執行上下文究竟作了些什麼?code

執行上下文(Execution Context)

什麼是執行上下文?來看定義對象

一段能夠執行的代碼在被執行的時候,會建立一個執行上下文,執行上下文,能夠理解爲當前代碼的執行環境

那麼什麼是可執行代碼呢?

  • 全局代碼(全局環境):你的代碼首次執行的默認環境,例如加載外部的js文件或者本地標籤內的代碼。全局代碼不包括任何function體內的代碼。 這個是默認的代碼運行環境,一旦代碼被載入,引擎最早進入的就是這個環境。
  • 函數代碼(函數環境):當函數被調用執行時,會進入當前函數中執行環境
  • eval(不建議使用,可忽略)

執行上下文(Execution Context)

對於每一個執行上下文都有三個重要的屬性,它們分別是

  • 變量對象(Variable object,VO)
  • 做用域鏈(Scope chain)
  • this的指向

執行上下文的變量對象(Variable object,VO))

咱們先來分析下變量對象Variable object,VO究竟是什麼

執行上下文在建立的時候會先建立變量對象voVO保存了函數中的全部形參,實參,局部變量,this指針等函數執行時的函數內部的數據狀況(此時尚未執行代碼),在全局執行上下文中叫作變量對象VO,在函數執行上下文中叫作活動對象AO,其實兩個是同樣的,具體以下

1.函數的形參和實參(若是是函數上下文)

  • 由名稱和對應值組成的一個變量對象的屬性被建立
  • 沒有實參傳入,形參就用undefined表示

2.函數的聲明,function max()

  • 由函數的名稱和內容來建立一個變量對象

3.變量的聲明,如 var a

  • 由名稱和undefined來建立一個變量對象

咱們還用分析執行上下文棧時的代碼改造下來舉栗子

function EC(a) {
            var b = 1
            console.log(b)
            console.log(a)
            var c = function (){}
            function c(){}
        }
        EC(2)
複製代碼

此時的AO爲,函數尚未被執行

AO = {
    arguments:{
        0:2,
        length: 1
    },
    a:2,
    b:undefined,
    c:undefined,
    d:reference to function d(){}
}
複製代碼

當執行EC函數的代碼時,AO會依次賦值,當執行完畢後,此時的AO

AO = {
    arguments:{
        0:2,
        length: 1
    },
    a:2
    b:1,
    c:reference to FunctionExpression "c"
    d:reference to function c(){}
} 
複製代碼

至此變量對象的建立過程就完結了

相關文章
相關標籤/搜索