什么是閉包
??閉包是一種抽象概念肮蛹,理解起來可能比較難困難眯停,再說閉包之前我們先了解下JavaScript的垃圾回收機制。
?隨著程序的運行抵怎,他們會因各種事情而占用計算機的內(nèi)存。如果程序運行了卻從不釋放不在需要的內(nèi)存阱洪,電腦最終會崩潰便贵。在一些語言中。像C,內(nèi)存管理是由程序員處理的冗荸。但在JavaScript中實現(xiàn)了自動回收機制承璃。
??當(dāng)函數(shù)執(zhí)行完畢時,管理內(nèi)存的當(dāng)?shù)胤椒〞⒑瘮?shù)中所有創(chuàng)建了的東西從內(nèi)存中移除蚌本。
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變量∏独颍現(xiàn)在我們可以回答什么是閉包了进萄,閉包就是阻止垃圾回收器將變量從內(nèi)存中移除的方法,使得在創(chuàng)建變量的執(zhí)行環(huán)境的外面能夠訪問到改變量。
讓我們再多看幾個閉包的事例:
var makePrison = function(priosner){
return function(){
return priosner;
}
}
var jokePrison = makePrison('Joke');
var mikePrison = makePrison('Mike');
閉包的原理
??我們知道了什么是閉包中鼠,但是他是怎么工作的呢可婶?答案就在執(zhí)行環(huán)境對象中。我們看一下上面的事例:
??當(dāng)調(diào)用makePrison時援雇,為了這次特定的調(diào)用創(chuàng)建了一個執(zhí)行環(huán)境對象矛渴,將傳入的值賦予給priosner(執(zhí)行環(huán)境對象是JavaScript引擎的一部分,在JavaScript中不能直接訪問)惫搏。
??我們調(diào)用了兩次makePrison將結(jié)果保存在 jokePrison 和mikePrison中具温。因為makePrison返回的是一個函數(shù),當(dāng)我們把結(jié)果賦值給jokePrison時筐赔,這個特定的執(zhí)行環(huán)境對象的引用計數(shù)置為1铣猩,因為引用計數(shù)大于0,垃圾回收器不會對這個對象進(jìn)行回收川陆。
當(dāng)我們再次調(diào)用makePrison剂习,并將它的返回值賦值給mikePrison時,創(chuàng)建了一個新的執(zhí)行環(huán)境對象较沪,并且它的引用計數(shù)也是1。盡管它們是通過同一個函數(shù)創(chuàng)建的失仁,但它們是不同的尸曼。
??如果再次調(diào)用jokePriso,它會使用 在調(diào)用makePrison 時創(chuàng)建的并且保存給jokePriso的執(zhí)行環(huán)境對象上設(shè)置的值萄焦。
tips
??每次調(diào)用函數(shù)時都會創(chuàng)建一個唯一的執(zhí)行環(huán)境對象控轿,函數(shù)執(zhí)行完后,執(zhí)行對象就會被丟棄拂封,除非調(diào)用者引用了它茬射。當(dāng)然,如果函數(shù)返回的數(shù)字冒签,就不能引用函數(shù)的執(zhí)行環(huán)境在抛。