閉包是js中的一大特色,也是一大難點。簡單來說,所謂閉包就是說,能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)。所以閉包可以理解成“定義在一個函數(shù)內(nèi)部的函數(shù)“。在本質(zhì)上,閉包是將函數(shù)內(nèi)部和函數(shù)外部連接起來的橋梁。
閉包的三大特點為:
1、函數(shù)嵌套函數(shù).
2、內(nèi)部函數(shù)可以訪問外部函數(shù)的變量.
3、參數(shù)和變量不會被回收.
舉例來說:
var n = 999;
function fn1(){
console.log(n);
}
fn1(); //999
另一方面,在函數(shù)外部自然無法讀取函數(shù)內(nèi)的局部變量。
function fn1(){
n = 999;
}
fn1();
console.log(n); // 999
這里有一個地方需要注意,函數(shù)內(nèi)部聲明變量的時候,一定要使用var命令。如果不用的話,你實際上聲明了一個全局變量。
function fn(){
var n = 10;
return function(){
console.log(n);
}
}
var fun = fn();
fun(); //10
這個例子中,變量n在fn方法外部是無法訪問的,但fn方法里面,嵌套了一個匿名函數(shù),通過return返回,fn作用域中的變量n,可以在匿名函數(shù)中訪問。并且當(dāng)fn方法執(zhí)行后,變量n所占內(nèi)存并不會釋放,以達到嵌套的函數(shù)還可以訪問的目的。閉包的作用在于,可以通過閉包,設(shè)計私有變量及方法。
二、如何從外部讀取局部變量?
出于種種原因,我們有時候需要得到函數(shù)內(nèi)的局部變量。但是,前面已經(jīng)說過了,正常情況下,這是辦不到的,只有通過變通方法才能實現(xiàn)。
那就是在函數(shù)的內(nèi)部,再定義一個函數(shù)。
function fn1(){
n = 999;
function fn2(){
console.log(n); //999
}
}
在上面的代碼中,函數(shù)fn2就被包括在函數(shù)fn1內(nèi)部,這時f1內(nèi)部的所有局部變量,對fn2都是可見的。但是反過來就不行,fn2內(nèi)部的局部變量對fn1就是不可見的。這就是javascript語言特有的‘鏈?zhǔn)阶饔糜颉Y(jié)構(gòu)(chain scope),子對象會一級一級地向上尋找所有父對象的變量。所以,父對象的所有變量,對子對象都是可見的,反之則不成立。
總結(jié):1、閉包是指有權(quán)訪問另一個函數(shù)作用域中的變量的函數(shù),創(chuàng)建閉包的最常見的方式就是在一個函數(shù)內(nèi)創(chuàng)建另一個函數(shù),通過另一個函數(shù)訪問這個函數(shù)的局部變量。閉包的缺點就是常駐內(nèi)存,會增大內(nèi)存使用量,使用不當(dāng)很容易造成內(nèi)存泄露。
2、不必糾結(jié)到底怎樣才算閉包,其實你寫的每一個函數(shù)都算作閉包,即使是全局函數(shù),你訪問函數(shù)外部的全局變量時,就是閉包的體現(xiàn)。