JS作用域鏈分析

JS聲明的變量會根據作用域鏈查找作用域是否聲明該變量,如果沒有,則查找上一個作用域,知道全局作用域。

// 全局作用域
function f1() {
    // f1作用域
    var a = 2
    function f2() {
        // f2作用域
        a = 1
        console.log(a)
    }
    
    f2()
    // var a = 2
    console.log(a)
}
f1()
console.log(a)

打印的結果爲1,1,報錯。在函數f2中,a被賦值爲1。根據作用域鏈,查看f2作用域,由於f2沒有聲明a,查找f1作用域,由於f1聲明a,所以f2的a是f1聲明的變量a。由於執行了f2函數,所以前面兩個打印的是1。最後一行代碼打印a,根據作用域鏈,查找全局作用域,由於全局作用域沒有聲明變量a,所以最後一行報沒有聲明變量a的錯誤。

// 全局作用域
function f1() {
    // f1作用域
    // var a = 2
    function f2() {
        // f2作用域
        a = 1
        console.log(a)
    }
    
    f2()
    var a = 2
    console.log(a)
}
f1()
console.log(a)

打印的結果爲1,2,報錯。在函數f2中,a被賦值爲1。根據作用域鏈,查看f2作用域,由於f2沒有聲明a,查找f1作用域,由於f1聲明a,所以f2的a是f1聲明的變量a。雖然聲明語句在f2函數執行之後,由於JS的變量提升,凡是使用聲明語句都會添加到作用域,所以f1的作用域已經存在a,也就是說f2從作用域查找的變量a是屬於f1的。執行f2函數後,f1的變量a被賦值爲1,。後面有執行了一直賦值語句,a被賦值爲2。所以前面2個打印的是1和2。最後一行打印變量a,根據作用域鏈,查找全局作用域,由於全局作用域沒有聲明變量a,所以最後一行報沒有聲明變量a的錯誤。

// 全局作用域
function f1() {
    // f1作用域
    // var a = 2
    function f2() {
        // f2作用域
        a = 1
        console.log(a)
    }
    
    f2()
    // var a = 2
    console.log(a)
}
f1()
console.log(a)

打印的結果爲1,1,1.。在函數f2中,a被賦值爲1。根據作用域鏈,查看f2作用域,由於f2沒有聲明a,查找f1作用域,由於f1沒有聲明變量a,查找全局作用域,由於全局作用域沒有聲明變量a,所以沒有找到變量a。但是需要執行賦值語句,所以在全局作用域聲明瞭變量a並執行了賦值操作。所以f1、f2的變量a是全局作用域的變量a,前面2個打印的是1和1。最後一行打印打印的是新增的全局作用域的變量a,a可以說是全局變量,所以最後一行打印的結果爲1。

// 全局作用域
function f1() {
    // f1作用域
    // var a = 2
    function f2() {
        // f2作用域
        // a = 1
        console.log(a)
    }
    
    f2()
    // var a = 2
    console.log(a)
}
f1()
console.log(a)

這裏在f2執行的時候直接報錯。根據作用域鏈,查找f2作用域、f1作用域、全局作用域都沒有找到變量a,所以直接報錯。

// 全局作用域
function f1() {
    // f1作用域
    // var a = 2
    function f2() {
        // f2作用域
        var a
        console.log(a)
    }
    
    f2()
    // var a = 2
    console.log(a)
}
f1()
console.log(a)

打印結果爲undefined,報錯。f2從作用域鏈查找到f2的局部變量a,因爲沒有賦值,所以f2打印的結果爲undefined,f1根據作用域鏈查找f1作用域和全局作用域,沒有找到變量a,所以報錯。

 

最後,JS一定要先聲明在使用變量!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章