閉包就是擁有許多變量和綁定這些變量環(huán)境的表達(dá)式,因此這些變量也是該表達(dá)式的一部分。
這個解釋估計會有許多人懵了不懂,我們暫且理解為,閉包是一個函數(shù)表達(dá)式,表達(dá)式綁定了一些變量的環(huán)境,然后看下面的代碼。
function f1(){
var n=999;
function f2(){
console.log(n);
}
return f2;//
返回內(nèi)部函數(shù)供外部調(diào)用。
}var result=f1();//
創(chuàng)建函數(shù)表達(dá)式,
result
引用了
f2
函數(shù),綁定變量
n
的環(huán)境。
result();//
輸出
999
變量的作用域
javascript
的變量分為兩種,全局變量和局部變量,全局變量無法直接引用局部變量,局部變量可以直接引用全局變量,這就是作用域。閉包就是為了解決全局變量無法引用局部變量的問題。
/**
*
直接引用全局變量
*/var n=999;function f1(){
alert(n);//
引用全局變量
}
f1(); // 999/**
*
無法直接引用局部變量
*/function f2(){
var abc=111;
}
alert(abc); // error
閉包獲取局部變量
function f1(){
var n=999;
function f2(){
console.log(n);
}
return f2;//
返回內(nèi)部函數(shù)供外部調(diào)用。
}var result=f1();
result();//
輸出
999
閉包需要注意的問題
閉包會將局部變量長期駐留在內(nèi)存中,很可能會造成內(nèi)存泄漏。這和java
的內(nèi)存引用很相似,長生命周期的變量引用短生命周期的變量時,會促使垃圾回收器無法回收短生命周期的變量。
function f1(){
var n=999;
nAdd=function(){n+=1}//
沒有使用
var
修飾,實(shí)為申明全局變量。
function f2(){
alert(n);
}
return f2;
}var result=f1();
result(); // 999
nAdd();
result(); // 1000
,再次調(diào)用也可以獲取到增后
n
的值,所以
n
沒有被回收
我們可以這么玩
function f1(){
var n=0;
function f2(){
n++;
function f3(){
n++;
function f4(){
n++;
console.log(n);
}
return f4;
}
return f3;
}
return f2;
}//
第一種調(diào)用方式
f1()()()();//
輸出
3//
第二種調(diào)用方式var result=f1()()();
result();//
輸出
3
多連括號方式調(diào)用,即為將父函數(shù)返回的子函數(shù)立即調(diào)用。
(function(){
var n=0;
console.log(n);
})();//
輸出
0//
也可以帶有函數(shù)名
(function f1(){
var n=0;
console.log(n);
})();//
輸出
0
這個叫做
申明函數(shù)并立即執(zhí)行。
來源: zengmianhui's personal blog