對(duì)于前端人員面試,出現(xiàn)頻率最多也是讓人最頭疼的就是面試官說(shuō):“請(qǐng)簡(jiǎn)單談一談你對(duì)閉包的理解”。對(duì)于這一個(gè)幾乎快被人問(wèn)爛的問(wèn)題,屢屢出現(xiàn)在我們面試或被面試的過(guò)程中的原因很簡(jiǎn)單--我們一直都在接觸閉包,卻很少去正確地對(duì)待它。

因?yàn)殚]包是因?yàn)镴S的一些語(yǔ)言特性而形成的,所以在談它之前我們首先要了解一下的知識(shí)點(diǎn)

1.執(zhí)行上下文
2.作用域
3.垃圾回收機(jī)制
4.函數(shù)嵌套

本文只會(huì)簡(jiǎn)單的談涉及到的內(nèi)容,如果知識(shí)點(diǎn)有遺漏的同學(xué)可以自行g(shù)oogle,接下來(lái)讓我們進(jìn)入正題!

1. 什么是閉包?

關(guān)于什么是閉包讓我們先看看《高級(jí)程序設(shè)計(jì)》和《JavaScript權(quán)威指南》中的說(shuō)法:

《高程》: 閉包是指有權(quán)訪(fǎng)問(wèn)另一個(gè)函數(shù)作用域中的變量的函數(shù),創(chuàng)建閉包的常見(jiàn)方式,就是在一個(gè)函數(shù)內(nèi)部創(chuàng)建另一個(gè)函數(shù)。

《權(quán)威指南》:和其他大多數(shù)現(xiàn)代編程語(yǔ)言一樣,JavaScript也采用詞法作用域,也就是說(shuō),函數(shù)的執(zhí)行依賴(lài)于變量作用域,這個(gè)作用域是在函數(shù)定義時(shí)決定的,而不是函數(shù)調(diào)用時(shí)決定的。為了實(shí)現(xiàn)這種詞法作用域,JavaScript函數(shù)對(duì)象的內(nèi)部狀態(tài)不僅包含函數(shù)的代碼邏輯,還必須引用當(dāng)前的作用域鏈。函數(shù)對(duì)象可以通過(guò)作用域鏈互相關(guān)聯(lián)起來(lái),函數(shù)體內(nèi)部的變量都可以保存在函數(shù)作用域內(nèi),這種特性在計(jì)算機(jī)科學(xué)文獻(xiàn)中稱(chēng)為“閉包”。

比較兩種說(shuō)法《高程》中的說(shuō)法太過(guò)抽象,我比較傾向于《權(quán)威指南》中的說(shuō)法,現(xiàn)在讓我們剝繭抽絲,一步一步的解釋這種說(shuō)法。

2. 解釋閉包,掃蕩閉包理解過(guò)程中產(chǎn)生的知識(shí)點(diǎn)

我們知道“JavaScript中沒(méi)有塊級(jí)作用域”,所謂“塊”,也就是大括號(hào)“{}”中間的語(yǔ)句(但是在ES6中已經(jīng)引入塊級(jí)作用域,這里不做討論).我們還知道在JavaScript中,在函數(shù)里面定義的變量,可以在函數(shù)里面被訪(fǎng)問(wèn),但是在函數(shù)外無(wú)法訪(fǎng)問(wèn),這也就形成了函數(shù)作用域,即如下代碼所示

var i = 1;
if(true){
    var j = 2;
}
console.log(i,j) // 1 2


function test(){
    var z = 3;
}

test();
console.log(z); //Uncau