拾遺記1:VOvsAO

js執行過程

當瀏覽器中的GUI線程解析html過程當中發現js代碼後,會告知Browser進程下載js文件。js文件下載完成後,js主引擎解析並執行js。因爲js主引擎和GUI線程互斥,因此在js執行過程當中,GUI線程掛起,html解析暫停,直至js代碼執行完畢。html

js主引擎解析並執行js可分爲三個步驟:瀏覽器

  1. 解釋階段(將得到的js字符串轉換爲計算機能夠識別的二進制)。
  2. 預編譯階段
  3. 執行階段

因爲js是腳本語言,所以預編譯階段和執行階段是幾乎同時進行的,即編譯一段代碼就執行一段代碼。閉包

執行上下文

js代碼在執行以前會生成執行環境(EC),也能夠稱爲執行上下文。函數

每當程序的執行流進入到一個可執行的代碼時,就進入到了一個執行環境中。

執行上下文包含三種:this

  1. 全局執行上下文。
  2. 函數執行上下文。
  3. eval執行上下文。

執行上下文對象

生成執行環境時生成執行上下文對象,執行上下文對象以下線程

fn.ExecutionContext = { 
    variableObject: // 函數中的 arguments、參數、局部成員 
    scopeChains: // 當前函數所在的父級做用域中的活動對象 
    this: {} // 當前函數內部的 this 指向 
}

VO

在執行上下文對象中包含variableObject屬性,也稱爲變量對象(VO)。此時,VO中的變量只是聲明,並無賦值。code

AO

當進入執行階段後,執行上下文會部分發生變化,以下:htm

fn.ExecutionContext = {
    activationObject: // 函數中的 arguments、參數、局部成員
    scopeChains: // 當前函數所在的父級做用域中的活動對象
    this: {} // 當前函數內部的 this 指向
}

此時,執行以前的變量對象(VO)變成了活動對象(AO),也就是完成了變量的賦值。對象

做用域鏈

做用域

做用域指明瞭一部分自由變量起做用的範圍,目前js包含三種,即:進程

  1. 全局做用域
  2. 函數做用域
  3. 塊級做用域(ES2015新增)

做用域鏈

函數在聲明的時候會肯定函數做用域,多個有關係的做用域合在一塊兒能夠造成做用域鏈。

function main() {
    // main函數內部的做用域鏈保存着全局做用域
    return function inner() {
       // inner內部的做用域鏈首先保存着main函數的做用域,還保存着全局做用域
    }
}

經過做用域鏈能夠完成變量值的查找,若是inner函數執行的時候須要a變量,inner函數首先查找本身的做用域,看是否認義了a變量,若是沒有,則向上查找main函數的做用域,若是沒有,則查找全局做用域,當整個查找鏈條都沒有找到a變量,則會提示a變量undefined,反之,若是在某個做用域內遭到變量a,那麼就中止查找。

做用域鏈要求只能從內向外查找,不能從外向內查找,也就是main函數查找變量時,只能查找自己做用域和全局做用域,而不能查找inner函數做用域。

使用閉包能夠突破變量做用域的限制,原來只能從一個做用域訪問外部做用域的成員,有了閉包以後,能夠在外部做用域訪問一個內部做用域的成員。
相關文章
相關標籤/搜索