JavaScript作用域相關的總結

影子同學發表於2019-04-16
這裡主要記錄在日常中對知識的學習,通過結合筆記與自身理解的方式嘗試寫下總結
文章對細節可能不會一一介紹解釋,內容僅作參考
複製程式碼

作用域指程式原始碼中定義變數的區域,規定了如何查詢變數即確定當前執行程式碼對變數的訪問許可權

JavaScript採用的是詞法作用域,也就是函式的作用域函式定義的時候就決定
與詞法作用域相反的是動態作用域,也就是函式的作用域是在函式呼叫的時候才決定,這裡僅供瞭解就好


在JavaScript中主要有全域性作用域函式作用域塊級作用域(ES6之前沒有)三個

  • 全域性作用域:顧名思義,是為最頂層最大的範圍
  • 函式作用域:僅在某個函式內部有效的範圍
  • 塊級作用域:僅在某個塊級程式碼內部有效的範圍

作用域是一個很抽象的概念,可以理解成一個地盤,具有

  • 獨立性:作用域包裹起來讓變數不會外洩,所以在不同作用域下同名變數不會有衝突 - 隔離變數
  • 分層與巢狀:作用域是有層級關係的,上下級關係的確定就看函式是在哪個作用域下定義的(在哪個作用域下定義就是哪個作用域的子作用域

內層作用域(子作用域)可以訪問外層作用域(父作用域)的變數,反之則不行。在查詢一個變數時,如果在本作用域內無定義,那麼就會往上一層父作用域查詢,一層一層向上直到全域性作用域,這種方式就成為了作用域鏈


再強調一次:作用域是在相應程式碼定義時就被建立(例如定義函式時決定相對應的函式作用域)


舉個栗子加深一下理解:

function foo() {
    var b = 2
    function bar(c) {
        var d = 3
        console.log(a, b, c, d)
    }
    bar(b * 3)
}
function hkk() {
    var e = 4
    console.log(a, e)
}
var a = 1
複製程式碼

假設走到這段程式碼的時候,最外層作用域是全域性作用域,目前的作用域層級為

[全域性作用域]
複製程式碼

定義foo函式,會有一個foo作用域產生

[全域性作用域[foo作用域]]
複製程式碼

然後走進foo裡面,定義bar函式,會有一個bar作用域產生

[全域性作用域 [foo作用域 [ bar作用域 ] ] ]
複製程式碼

繞出來後,還定義了hkk函式,會有一個hkk作用域產生

[全域性作用域 [foo作用域 [ bar作用域 ], hkk作用域]]
複製程式碼

在接下來變數的查詢就會依賴這個作用域鏈 比如說在上面程式碼會有

  • bar -> foo -> 全域性
  • hkk -> 全域性

在函式執行時變數的查詢就會變成這樣:

function foo() {
    var b = 2
    function bar(c) {
        var d = 3
        console.log(a, b, c, d)
        // a: 在bar這裡找不到,去foo那裡找找。foo也找不到呢,再上去全域性找找。在全域性找到了 -> 最後得出這個值要在全域性作用域下拿到
        // b: 在bar這裡找不到,去foo那裡找找。在foo找到了 -> 最後得出這個值要在foo作用域下拿到
        // c: 在bar這裡找到了 -> 最後得出這個值要在bar作用域下拿到
        // d: 在bar這裡找到了 -> 最後得出這個值要在bar作用域下拿到
    }
    bar(b * 3)
}
function hkk() {
    var e = 4
    console.log(a, e)
    // a: 在hkk這裡找不到,上去全域性找找。在全域性找到了 -> 最後得出這個值要在全域性作用域下拿到
    // c: 在hkk這裡找到了 -> 最後得出這個值要在hkk作用域下拿到
}
var a = 1
複製程式碼

作用域是執行上下文知識的前置知識

可以想象成: 我要辦一座學校(全域性),會有多個年級(函式/塊級作用域),然後呢每個年級裡面又有多個班級(子函式/塊級作用域),每個班級又會有跟細的組織結構

但是呢 我這裡只是想好了怎麼安排制度(某個班級考試時,如果班級自己沒有試卷,那需要的試卷應該向對應的年級拿,年級沒有,再去找學校要),但至於執行起來後,年級有多少試卷,是否還有作業,就要看年級私底下的安排了(這個這裡先不去理解 看看就好)

相關文章