閉包(closure)是javascript的一大難點(diǎn),也是它的特色。很多高級(jí)應(yīng)用都要依靠閉包來實(shí)現(xiàn)。
1、變量作用域
要理解閉包,首先要理解javascript的特殊的變量作用域。
變量的作用域無非就兩種:全局變量和局部變量。
javascript語言的特別之處就在于:函數(shù)內(nèi)部可以直接讀取全局變量,但是在函數(shù)外部無法讀取函數(shù)內(nèi)部的局部變量。
注意點(diǎn):在函數(shù)內(nèi)部聲明變量的時(shí)候,一定要使用var命令。如果不用的話,你實(shí)際上聲明的是一個(gè)全局變量!
2、如何從外部讀取函數(shù)內(nèi)部的局部變量?
出于種種原因,我們有時(shí)候需要獲取到函數(shù)內(nèi)部的局部變量。但是,上面已經(jīng)說過了,正常情況下,這是辦不到的!只有通過變通的方法才能實(shí)現(xiàn)。
那就是在函數(shù)內(nèi)部,再定義一個(gè)函數(shù)。
function f1(){
var n=999;
function f2(){
alert(n); // 999
}
}
在上面的代碼中,函數(shù)f2就被包括在函數(shù)f1內(nèi)部,這時(shí)f1內(nèi)部的所有局部變量,對(duì)f2都是可見的。但是反過來就不行,f2內(nèi)部的局部變量,對(duì)f1就是不可見的。
這就是Javascript語言特有的“鏈?zhǔn)阶饔糜颉苯Y(jié)構(gòu)(chain scope),
子對(duì)象會(huì)一級(jí)一級(jí)地向上尋找所有父對(duì)象的變量。所以,父對(duì)象的所有變量,對(duì)子對(duì)象都是可見的,反之則不成立。
既然f2可以讀取f1中的局部變量,那么只要把f2作為返回值,我們不就可以在f1外部讀取它的內(nèi)部變量了嗎!
3、閉包的概念
上面代碼中的f2函數(shù),就是閉包。
各種專業(yè)文獻(xiàn)的閉包定義都非常抽象,我的理解是: 閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)。
由于在javascript中,只有函數(shù)內(nèi)部的子函數(shù)才能讀取局部變量,所以說,閉包可以簡單理解成“定義在一個(gè)函數(shù)內(nèi)部的函數(shù)“。
所以,在本質(zhì)上,閉包是將函數(shù)內(nèi)部和函數(shù)外部連接起來的橋梁。
4、javascript 閉包的好處及壞處
閉包javascript 是最強(qiáng)大的特征之一,它允許函數(shù)訪問局部作用域之外的函數(shù)。
創(chuàng)建閉包的常見方式:就是在一個(gè)函數(shù)里創(chuàng)建另一個(gè)函數(shù)
?。踛avascript] view plain copyfunction fun(){
return function{
alert(“hello”);
}
}
閉包的好處有:
1.緩存
2.面向?qū)ο笾械膶?duì)象
3.實(shí)現(xiàn)封裝,防止變量跑到外層作用域中,發(fā)生命名沖突
4.匿名自執(zhí)行函數(shù),匿名自執(zhí)行函數(shù)可以減小內(nèi)存消耗
以上四條詳見(http://blog.csdn.net/sunlylorn/article/details/6534610)
閉包的壞處:
1.內(nèi)存消耗
通常來說,函數(shù)的活動(dòng)對(duì)象會(huì)隨著執(zhí)行期上下文一起銷毀,但是,由于閉包引用另外一個(gè)函數(shù)的活動(dòng)對(duì)象,因此這個(gè)活動(dòng)對(duì)象無法被銷毀,這意味著,閉包比一般的函數(shù)需要更多的內(nèi)存消耗。尤其在IE瀏覽器中需要關(guān)注。由于IE使用非原生javascript對(duì)象實(shí)現(xiàn)DOM對(duì)象,因此閉包會(huì)導(dǎo)致內(nèi)存泄露問題,例如:
[javascript] view plain copyfunction A(){
var a=document.createElement(“div”),//
msg=“Hello”;
a.onclick=function(){
alert(msg);
}
}
A();
以上的閉包會(huì)在IE下導(dǎo)致內(nèi)存泄露,假設(shè)A()執(zhí)行時(shí)創(chuàng)建的作用域?qū)ο骃copeA,ScopeA引用了DOM對(duì)象a,DOM對(duì)象a
引用了function(aleert(msg)),函數(shù)function(alert(msg))引用了ScopeA,這是一個(gè)循環(huán)引用,在IE會(huì)導(dǎo)致內(nèi)存泄露。
2.性能問題
使用閉包時(shí),會(huì)涉及到跨作用域訪問,每次訪問都會(huì)導(dǎo)致性能損失。
因此在腳本中,最好小心使用閉包,它同時(shí)會(huì)涉及到內(nèi)存和速度問題。不過我們可以通過把跨作用域變量存儲(chǔ)在局部變量中,然后直接訪問局部變量,來減輕對(duì)執(zhí)行速度的影響。
評(píng)論
查看更多