閉包是有權(quán)訪問另外一個函數(shù)作用域中變量的函數(shù)
在了解閉包之前跛十,需要先了解幾個概念,具體如下:
當(dāng)某個環(huán)境被調(diào)用的時候,會創(chuàng)建一個執(zhí)行環(huán)境以及相應(yīng)的作用域鏈池充。然后,使用arguments和其他命名參數(shù)的值來初始化函數(shù)的活動對象缎讼。但在作用域鏈中收夸,外部函數(shù)的活動對象始終在第二位,外部函數(shù)的外部函數(shù)血崭,排在了第三位卧惜,以此類推厘灼,排外最尾部的是全局執(zhí)行環(huán)境。
執(zhí)行環(huán)境
執(zhí)行環(huán)境(execution context)又稱為執(zhí)行上下文序苏,有時直接稱之為環(huán)境手幢,是JavaScript中一個很重要的概念。通過它可以判斷變量或者函數(shù)是否有權(quán)訪問其他數(shù)據(jù)忱详。每個執(zhí)行環(huán)境都有一個變量對象(variable object)围来,這個對象中包含了在這個環(huán)境中定義的所有的變量和函數(shù)。全局執(zhí)行環(huán)境是最底層的執(zhí)行環(huán)境匈睁。在web瀏覽器中监透,全局執(zhí)行環(huán)境被認為是window對象,因此所有的全局變量和函數(shù)都是作為window對象的屬性和方法創(chuàng)建的航唆。當(dāng)某個執(zhí)行環(huán)境里面的代碼全部執(zhí)行完畢的時候胀蛮,該環(huán)境就會被銷毀,包括該環(huán)境中的所有變量糯钙,定義的函數(shù)也會隨之銷毀粪狼。而全局執(zhí)行環(huán)境是一直到關(guān)閉瀏覽器才會被銷毀。
每個函數(shù)都有自己的執(zhí)行環(huán)境任岸,當(dāng)執(zhí)行流進入這個函數(shù)的時候再榄,函數(shù)的環(huán)境就會被推入一個環(huán)境棧中,當(dāng)函數(shù)執(zhí)行完畢后享潜,棧將其環(huán)境彈出困鸥。
作用域鏈
當(dāng)代碼在環(huán)境中執(zhí)行時,會創(chuàng)建變量對象的一個作用域鏈剑按。作用域鏈的作用是保證對執(zhí)行環(huán)境有權(quán)訪問的所有變量和函數(shù)的有序訪問疾就。他的本質(zhì)上是一個指向變量對象的指針列表。其第一個節(jié)點里有當(dāng)前環(huán)境的變量對象(如果環(huán)境是函數(shù)艺蝴,這把活動對象(一開始為arguments)作為變量對象)猬腰。第二個節(jié)點為其環(huán)境的下一個包含環(huán)境的變量對象以此類推,一直到全局執(zhí)行環(huán)境包含的變量對象(全局環(huán)境沒有arguments)猜敢。
尋找某一個變量或者函數(shù)時漆诽,都是沿著作用域鏈開始層層往后搜索,一直到找到為止锣枝,如果找不到,則返回undefined兰英。
閉包
閉包的概念其實并不復(fù)雜撇叁,就是有權(quán)訪問另外一個函數(shù)作用域中變量的函數(shù)。通常的創(chuàng)建方式為一個函數(shù)內(nèi)部創(chuàng)建另一個函數(shù)畦贸。
當(dāng)然陨闹,還有一種更廣泛的理解楞捂,只要是內(nèi)部函數(shù)以值傳遞的形式,或者當(dāng)做參數(shù)趋厉,傳遞給外部函數(shù)寨闹,那么就發(fā)生了閉包
PS
1.閉包中內(nèi)部函數(shù)取得外部函數(shù)的變量永遠是最后一個值。
2.閉包中君账,內(nèi)部函數(shù)永遠無法取到外部函數(shù)的this和arguments繁堡,只能取到活動對象。