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