《JavaScript高級程序設計》總結(五)—— 做用域鏈

先來複習一下,執行上下文的構成bash

執行上下文函數

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

以前說了變量對象,如今來講下另外兩個this

做用域鏈(Scope chain)

通俗地講,當聲明一個函數時,局部做用域一級一級向上包起來,就是做用域鏈。spa

咱們從函數定義到執行一步一步來講明code

當函數定義的時候

當函數被定義的時候,會讀取函數內部的一個屬性,[[scope]]屬性來保存就會保存全部父變量對象到其中,能夠理解 [[scope]] 就是全部父變量對象的層級鏈對象

function a(){
    function b(){
        
    }
}
複製代碼

分析一下,當函數建立時,各自的[[scope]]爲作用域

a.[[scope] = [
   globalContext.VO
]

b.[[scope]] = [
    aContext.AO,
    globalContext.VO
];
複製代碼

當函數激活的時候

當函數激活的時候,建立VO/AO。並將其加入做用域鏈的第一位,做用域鏈(scope)到如今就建立完畢了string

寫個例子結合函數的上下文,變量對象等知識說明下做用域鏈

var global = '全局變量'
function abs(){
    a = 1
    console.log(a)
}
abs()
複製代碼

1.函數abs被建立,將做用域鏈保存到[[scope]]中it

abs.[[scope]] = [
     globalContext.VO
]
複製代碼

2.abs函數開始執行,此時建立abs函數的執行上下文,併入棧io

ECstack = [
    absContext
    globalContext
]
複製代碼

3.abs作正式執行前的準備工做,將[[scope]]屬性做爲做用域鏈,此時的abs執行上下文

absContext = {
     Scope: abs.[[scope]],
}
複製代碼

4.初始化變量對象,VO/AO

absContext = {
    AO: {
        arguments: {
            length: 0
        },
        a: undefined
    },
    Scope:abs.[[scope]]
}
複製代碼

5.將活動對象AO加到做用域鏈的頂端

absContext = {
    AO: {
        arguments: {
            length: 0
        },
        a: undefined
    },
    Scope:[AO,abs.[[scope]]]
}
複製代碼

至此,準備工做完成

6.隨着函數的進行,AO開始進行賦值工做

checkscopeContext = {
    AO: {
        arguments: {
            length: 0
        },
        a: 1
    },
    Scope: [AO, [[Scope]]]
}
複製代碼

7.在做用域鏈中找到a的值並打印

8.abs執行完畢,abs的執行上下文棧彈出

ECstack = [
    globalContext
]
複製代碼
相關文章
相關標籤/搜索