閉包:
形成閉包的條件:
- 1、函數(shù)嵌套函數(shù)(有作用域的嵌套)
- 2、內(nèi)部函數(shù)使用了外部的變量/參數(shù)
作用:
- 內(nèi)部函數(shù)使用的外部函數(shù)變量/參數(shù)會(huì)被永久的保存
例:
~function (){ //函數(shù)1
var num = 0; // 外部變量
document.onclick = function (){ // 函數(shù)2 函數(shù)嵌套函數(shù)
num ++; // 內(nèi)部調(diào)用到外部變量
console.log( num )
}
}();
符合上面的條件:形成一個(gè)閉包 num 永久的保存
垃圾回收機(jī)制
+當(dāng)所有環(huán)境都還在有對(duì)某個(gè)對(duì)象/數(shù)據(jù)的引用時(shí),這個(gè)數(shù)據(jù)會(huì)被回收的
1、變量引用時(shí):
var a = [ 1 , 2 , 3 ]
.
. 代碼 中間這分部不會(huì)被回收
...
alert( a );
.
.沒有對(duì)a再引用 這時(shí)候a就會(huì)被回收
.
...
2、函數(shù)引用時(shí)
function fn(){
var b = 0;
b++;
alert( b );
}
.
. 代碼 fn里的 var b = 0 b++ alert( b ) 不會(huì)被回收
....
fn();
.
. 下面的代碼沒有對(duì)fn引用 fn里的函數(shù)體會(huì) var b = 0 b++ alert( b ) 被回收掉
....
案例分析:
<script>
function fn(){
var a = 1;
return function (){
alert( ++a ) // 形成閉包 a不會(huì)被回收 永久的被保存
}
}
var fn2 = fn(); //fn執(zhí)行 返回function (){ alert( a++ ) }
//a不會(huì)被回收 存在于 fn()這個(gè)作用域里
fn2(); //fn2()執(zhí)行 彈出2 a = 2
fn2(); //fn2()執(zhí)行 a就是上面 2 ; a++ 彈出3
</script>
<script>
function fn(){
var a = 0;
return function (){ //形成閉包
a++;
console.log( a );
}
}
var fn2 = fn(); //返回是function (){ a++ ; console.log( a ) }
var fn3 = fn(); //返回是function (){ a++ ; console.log( a ) } 這2個(gè)a是完全不一樣的 只是長得一樣而已
fn2(); //fn2()執(zhí)行 產(chǎn)生一個(gè)新的作用域 a++ 彈出 2 這里的a會(huì)存放在fn2()這個(gè)作用域里
fn2(); //fn2() 再 a ++ 上面a已經(jīng)是2 彈出3
fn3(); // fn3() 執(zhí)行 產(chǎn)生一個(gè)新的作用域 a++ 彈出 2 這里的a會(huì)存放在fn3()這個(gè)作用域里
</script>

圖解
<script>
function fn( ) {
var a = 1;
fn2( a ); //這里沒有形成閉包 都沒有函數(shù)嵌套函數(shù)
}
function fn2( a ) {
a++;
alert( a );
}
fn();
</script>
閉包的優(yōu)缺點(diǎn):
- 閉包的優(yōu)點(diǎn)就是缺點(diǎn)
使用的變量會(huì)被永久存儲(chǔ)(只有關(guān)閉頁面時(shí)才會(huì)被釋放),我們可以對(duì)同一個(gè)變量重復(fù)利用
<script>
function fn(){
var num = 0; //我們記錄點(diǎn)了多少次時(shí)
// 如果不用閉包就要在頂層下聲明一個(gè)變量 用來記錄 在全局聲明會(huì)對(duì)頂層有污染
return function ( ) {
num ++;
console.log( num );
}
}
document.onclick = fn();
</script>
缺點(diǎn)
- 使用變量會(huì)被永久保存,當(dāng)大量使用閉包時(shí),會(huì)對(duì)內(nèi)存的消耗有點(diǎn)點(diǎn)高