什么是閉包
??閉包是一種抽象概念,理解起來可能比較難困難,再說閉包之前我們先了解下JavaScript的垃圾回收機制。
?隨著程序的運行,他們會因各種事情而占用計算機的內存。如果程序運行了卻從不釋放不在需要的內存,電腦最終會崩潰。在一些語言中。像C,內存管理是由程序員處理的。但在JavaScript中實現(xiàn)了自動回收機制。
??當函數(shù)執(zhí)行完畢時,管理內存的當?shù)胤椒〞⒑瘮?shù)中所有創(chuàng)建了的東西從內存中移除。
var prison = function(){
var prisoner = 'Joke';
}
prison();
一旦prison執(zhí)行完畢,我們就不需要訪問prisoner變量了。
var prison = (function(){
var prisoner = 'Joke';
return {prisoner:prisoner}
})()
console.log(prisoner:prisoner)
這和上述一樣prisoner:prisoner并不會訪問函數(shù)中的prisoner變量,但下面這個就不一樣了:
var prison = (function(){
var prisoner = 'Joke';
return {
prisoner:function(){
return prisoner;
}
}
})()
console.log(prisoner:prisoner())
??現(xiàn)在每次執(zhí)行prisoner:prisoner(),都會訪問prison函數(shù)中的prisoner變量,這樣垃圾回收機制就不能移除 prisoner變量?,F(xiàn)在我們可以回答什么是閉包了,閉包就是阻止垃圾回收器將變量從內存中移除的方法,使得在創(chuàng)建變量的執(zhí)行環(huán)境的外面能夠訪問到改變量。
讓我們再多看幾個閉包的事例:
var makePrison = function(priosner){
return function(){
return priosner;
}
}
var jokePrison = makePrison('Joke');
var mikePrison = makePrison('Mike');
閉包的原理
??我們知道了什么是閉包,但是他是怎么工作的呢?答案就在執(zhí)行環(huán)境對象中。我們看一下上面的事例:
??當調用makePrison時,為了這次特定的調用創(chuàng)建了一個執(zhí)行環(huán)境對象,將傳入的值賦予給priosner(執(zhí)行環(huán)境對象是JavaScript引擎的一部分,在JavaScript中不能直接訪問)。
??我們調用了兩次makePrison將結果保存在 jokePrison 和mikePrison中。因為makePrison返回的是一個函數(shù),當我們把結果賦值給jokePrison時,這個特定的執(zhí)行環(huán)境對象的引用計數(shù)置為1,因為引用計數(shù)大于0,垃圾回收器不會對這個對象進行回收。
當我們再次調用makePrison,并將它的返回值賦值給mikePrison時,創(chuàng)建了一個新的執(zhí)行環(huán)境對象,并且它的引用計數(shù)也是1。盡管它們是通過同一個函數(shù)創(chuàng)建的,但它們是不同的。
??如果再次調用jokePriso,它會使用 在調用makePrison 時創(chuàng)建的并且保存給jokePriso的執(zhí)行環(huán)境對象上設置的值。
tips
??每次調用函數(shù)時都會創(chuàng)建一個唯一的執(zhí)行環(huán)境對象,函數(shù)執(zhí)行完后,執(zhí)行對象就會被丟棄,除非調用者引用了它。當然,如果函數(shù)返回的數(shù)字,就不能引用函數(shù)的執(zhí)行環(huán)境。