談談js中的閉包

閉包的形成跟變量的作用域以及變量的生存周期密切相關

一、變量的作用域,是指變量的有效范圍

當在函數(shù)中聲明一個變量的時候,如果該變量前面沒有帶上關鍵字?var,這個變量就會成為全局變量 ,這當然是一種很容易造成命名沖突的做法。

另外一種情況是用?var?關鍵字在函數(shù)中聲明變量,這時候的變量即是局部變量,只有在該函數(shù)內(nèi)部才能訪問到這個變量,在函數(shù)外面是訪問不到的。

例:變量的搜索是從內(nèi)到外而非從外到 內(nèi)的

vara=1;

varfunc1 =function(){

varb=2;

varfunc2 =function(){

varc=3;

console.log ( b );// 輸出:2

console.log ( a );// 輸出:1

? ? }

? ? func2();

console.log(c);//輸出:Uncaught ReferenceError: c is not defined

};

func1();

二、變量的生存周期

對于全局變量來說,全局變量的生存周期當然是的永久,除非我們主動銷毀這個全局變量。

而對于在函數(shù)內(nèi)用var關鍵字聲明的局部變量來說,當退出函數(shù)時,這些局部變量即失去了 它們的價值,它們都會隨著函數(shù)的調(diào)用的結束而銷毀

例一:

varfunc =function(){

vara=1;

returnfunction(){

? ? ? ? a++;

console.log(a);

? ? }

};

varf=func();

f();// 輸出:2

f();// 輸出:3

f();// 輸出:4

f();// 輸出:5

跟我們之前的結論相反,上面的例子在當退出函數(shù)后,局部變量a?并沒有消失,而是似乎一直在某個地方 存活著。這是因為當執(zhí)行?var f = func();時,f?返回了一個名函數(shù)的引用,它可以問到func()?被調(diào)用時產(chǎn)生的環(huán)境,而局部變量?a?一直處在這個環(huán)境里。既然外局部變量所在的環(huán)境還能被外 界訪問,這個局部變量就有了不被銷毀的理由。在這里生了一個閉包結構,局部變量的聲明看起來被延續(xù)了。

例二,假設頁面上有 5 個 div 節(jié)點,我們通過循環(huán)來給每個 div綁定 onclick 事件,按照索引順序,點擊第 1 個 div 時彈出 0,點擊第 2 個 div 時出 1,以此類

varnodes =document.getElementsByTagName('div');

for(vari=0,len=nodes.length;i<len;i++){

nodes[ i ].onclick =function(){

? ? ? ? alert(i);

? ? }

};

測試這段代碼會發(fā)現(xiàn),無論點擊哪個 div,最后彈出的結果都是 5

這是因為?div?節(jié)點的?onclick?事件是被異步觸發(fā)的,當事件被觸發(fā)的時候,for循環(huán)早已結束,此時 i 的值已經(jīng)是?5,

所以在?div的?onclick?事件函數(shù)中順著作用域鏈從內(nèi)到外查找變量 i 時,查找到的值總是?5。

解決方法是在閉包的幫助下,每次循環(huán)的i?值都封閉起來。當在事件函數(shù)中順著作用域鏈從內(nèi)到外查找變量?i時,會先找到被封閉在閉包環(huán)境中的i,如果有5個div,這里的i分別 是?0,1,2,3,4

for(vari=0,len=nodes.length;i<len;i++){

(function( i ){

nodes[ i ].onclick =function(){

console.log(i);

? ? ? ? }

? ? })(i)

};

三、閉包的作用

1、封裝變量—-閉包可以幫助一些不需要暴露在全局的變量封裝成“私有變量”

例一,計算乘積

varmult =function(){

vara=1;

for(vari=0,l=arguments.length;i<l;i++){

a = a *arguments[i];

? ? }

returna;

};

2、延續(xù)局部變量的壽命

四、閉包與內(nèi)存泄漏

functiona(){

vari =0;

functionb(){

console.log(++i);

? ? }

returnb;

}

varc = a();

c();

首先有一個封閉的函數(shù)a(即自定義的一個function a()方法),該函數(shù)內(nèi)部的變量b(局部變量/局部方法)外部無法直接調(diào)用;但如果把這個函數(shù)賦值給一個全部變量c時,

全局變量c就獲取到了函數(shù)局部變量b的值,從而使局部變量b的值得到了保存,即延長了一個局部變量b的生命周期,除非主動銷毀這個全局變量c。

此時,我們也就制造出來了一個“閉包”。簡單說“閉包是指有權限訪問另一個函數(shù)作用域的變量的函數(shù)”。

在這個過程中,因為局部變量b的聲明周期延長,使得Javascript的垃圾回收機制不會收回函數(shù)a所占用的資源,因為函數(shù)a的局部變量b的執(zhí)行需要依賴函數(shù)a中的變量。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容