1. 程式人生 > >JavaScript難點系列(四):作用域

JavaScript難點系列(四):作用域

文章 this 的確 空間 console 知識點 人的 歧義 查找

深入了解js這門語言後,才發現它有著諸多眾所周知的難點(例如:閉包、原型鏈、內存空間等)。有的是因為js的設計缺陷導致的,而有的則是js的優點。不管如何,總需要去學會它們,在學習過程中我覺得只看別人的文章並不能做到深刻理解,所以我決定寫這一系列的文章來記錄我所學習到的知識點,也方便自己以後回顧,如有寫錯的地方歡迎指正。
廢話不多說,馬上進入正題!

函數作用域

有句人人皆知的江湖傳言:“JavaScript沒有塊級作用域”。當然這是ES6之前的事了,我們需要知道的是JS除了全局作用域外就是函數作用域了。JS中的作用域和this指定機制恰好相反,它是在函數創建時就確定的,而不是調用的時候。
來看一段簡單的代碼

function foo() {
    var a = 100
    function bar() {
        var a = 200
    }
}

上面這段代碼分別形成了全局作用域、foo作用域和bar作用域。而且作用域有上下級的關系(也可以理解為包含關系),這個上下級關系的確定就看函數是在誰的作用域下創建(不是執行)。上述代碼中,foo作用域下創建了bar函數,那麽foo作用域就是bar作用域的上級。

靜態作用域

作用域分兩種,一種是動態作用域(函數的作用域在函數調用的時候才決定),一種是靜態作用域(函數的作用域在定義時就已經決定,也叫詞法作用域)。JS采用的是靜態作用域,來看個例子就明白了。

var a = 1
function foo() {
    console.log(a)
}
function bar(f) {
    var a = 2
    (function() {
        f()
    })()
}
bar(foo)  // 1 

坊間一直有種說法,說是查找變量時如果在該函數作用域找不到,就去它的父級作用域找。其實這種說法是很容易讓人產生歧義的。我們從靜態作用域的角度去分析,foo函數的作用域在它定義時就已經確定了,所以foo作用域的上級作用域是全局作用域,當foo函數在bar函數內被調用時,它發現找不到變量a,於是去上級作用域也就是全局作用域尋找,自然結果就是a = 1。

JavaScript難點系列(四):作用域