理解閉包,先了解一下Javascript變量的做用域。有兩種,全局變量和局部變量。安全
例子1:閉包
<script> var a = 0; function fun(){ var b = 0; console(a+" "+b); } </script>
a是全局變量,b是局部變量。函數內部能夠直接讀取全局變量,可是在函數外部沒法讀取函數內部的局部變量。函數
如何從外部讀取函數內部的局部變量?性能
例子2:spa
function fun(num){ var b = 0; b += num; return b; } var re_b = fun(1); console.log(re_b); //1 re_b = fun(2); console.log(re_b); //2
fun()將局部變量b做爲返回結果;code
例子3:對象
function fun(){ var b = 0; function fun2(num){ b += num; return b; } return fun2 } var re_b = fun(); console.log(re_b(1)); //1 console.log(re_b(2)); //3
簡單分析一下例子3代碼:blog
定義普通函數fun;ip
在fun中定義變量b,普通函數fun2(參數),返回fun2;內存
在fun2中將參數num與b相加後賦予b,返回b;
執行fun,並把返回結果賦予re_b,此時re_b的類型爲function;
執行re_b(1),結果輸出1(0+1);
執行re_b(2),結果輸出3(1+2);
上述方法即爲閉包。
在瞭解閉包的做用以前,咱們先了解一下 Javascript 中的 垃圾回收 機制,在 Javascript 中,若是一個對象再也不被引用,那麼這個對象就會被 GC 回收,不然這個對象一直會保存在內存中。
例子2中,執行完fun,變量b就會被釋放回收;
例子3中,fun2定義在fun中,即fun2依賴於fun,全局變量re_b引用fun2,fun就間接被引用,即fun和fun2與re_b共存亡。只要re_b沒被釋放回收,變量b就一直在內存中。這也就是閉包的做用,fun執行完並返回後,閉包使得Javascript的垃圾回收機制GC不會收回fun所佔用的資源。
一句話說,當一個內部函數被其外部函數以外的變量引用時,就造成了一個閉包。
閉包的應用場景:保護函數內的變量安全;在內存中維持一個變量;經過保護變量的安全實現JS私有屬性和私有方法。
閉包的一個簡單應用:
for(var i=0;i<5;i++){ setTimeout(function(){ console.log(i) },1000*i) }
結果爲,每秒鐘輸出一個5,一共輸出5次。
for(var i=0;i<5;i++){ (function fun(i) { setTimeout(function(){ console.log(i) },1000*i) })(i) }
結果爲,每秒鐘輸出一個數,0,1,2,3,4。
第一個例子中每次循環中的setTimeout回調函數記住的i的值是for循環做用域中的值,此時都是5,而第二個例子記住的i的數爲setTimeout的父級做用域自執行函數中的i的值,依次爲0,1,2,3,4。
注意點:因爲閉包會使得函數中的變量都被保存在內存中,內存消耗很大,濫用閉包,會形成網頁的性能問題,在IE中可能致使內存泄露