1. 程式人生 > >[JavaScript]JavaScript中的函數(2)

[JavaScript]JavaScript中的函數(2)

ron 總結 href 尋找 tro http cal con 如果

承接上一篇博文的總結,這篇博文是利用代碼+畫圖的形式,梳理一下對於函數作用域和閉包的理解。

函數中的作用域

在 JavaScript 中, 對象和函數同樣也是變量。
在 JavaScript 中, 作用域為可訪問變量,對象,函數的集合。

首先我們聲明一個函數,然後在函數內部聲明並賦值一個變量:

function fn(){
    var x = 3
    console.log(x)
}
fn.call()    //3

技術分享圖片

在函數fn中就產生了一個作用域,要求打印x的值時,函數就會在自身內部尋找這個x,然後把結果打出來。

在函數內部再次聲明一個函數的話,情況會變成什麽樣呢:

function fn(){
    var x = 3
    // console.log(x)
    function fn1(){
        var x = 4
        console.log(x)
    }
    fn1.call()
}
fn.call()   //4

技術分享圖片

函數fn1在fn作用域內創造了一個子作用域,打印的時候不使用fn中的變量x,而是使用了這個子作用域內的變量x。

如果fn1中沒有聲明變量x,他會打印出什麽呢?

function fn(){
    var x = 3
    function fn1(){
        console.log(x)
    }
    fn1.call()
}
fn.call()   //3

技術分享圖片

他會去尋找fn中的x,然後把他打印出來。

如果函數fn作用域內也不存在這個變量呢?

var x = 5
function fn(){
    function fn1(){
        console.log(x)
    }
    fn1.call()
}
fn.call()   //5

技術分享圖片

由此可以看出:在調用函數作用域(fn1)中的某個變量(x)時,他會先在自身作用域中尋找這個變量;如果這個變量沒有找到,那麽這個函數可以訪問上一級作用域(fn)中的變量(x);如果這個變量還沒有找到,那麽這個函數可以訪問更上一級,即全局作用域(window)中的x。

註意

在理解作用域的同時,我們要十分註意變量提升的問題。

比如:

function fn(){
    function fn1(){
        console.log(x)
        var x = 5
    }
    fn1.call()
}
fn.call()   //undefined

為什麽會打印出了undefined呢?

因為這段代碼實際上表達的意思是這樣:

function fn(){
    function fn1(){
        var x
        console.log(x)
        x = 5
    }
    fn1.call()
}
fn.call()   //undefined

變量x只是做出了聲明,但是並沒有賦值,所以打印出來是undefined。

閉包

既然理解了函數作用域,就能理解閉包了。

「函數」和「函數內部能訪問到的變量」(也叫環境)的總和,就是一個閉包。

比如上文這張圖:

技術分享圖片

函數fn1加上他可以訪問的位於函數fn的作用域內的變量x,就是一個閉包。

關於閉包的更詳細的解釋,可以看看方應杭方老師的這篇文章,我們充分理解,學以致用,就可以了。

[JavaScript]JavaScript中的函數(2)