一、《高級程序設計》上,這樣說:當在函數內部定義了其餘函數時候,就建立了閉包。閉包有權訪問包含函數內部的全部變量。也就是數組
函數嵌套函數,內部函數能夠引用外部函數的參數和變量,參數和變量不會被垃圾回收機制所收回。 |
這個引用纔是關鍵,由於這個引用的存在,外部函數成了這個引用運行的上下文,迫使垃圾回收機制GC不能回收這條鏈上所佔用的資源。而若是沒有這個引用,則跟通常函數同樣,函數運行完資源就會被回收。我看了做用域鏈的概念,感受看懂了做用域鏈,再來理解閉包就簡單地多。閉包實質是內存中開闢一塊地址,用於保存上下文。在另外一個函數內部定義的函數會將包含函數(即外部函數)的活動對象添加到它的做用域鏈中。閉包函數調用的外部函數變量都是引用,所以當執行相似於a[i]=function(){return i;}這種不能當即執行的出結果給數組賦值時候,就會出現問題。解決辦法就是使用匿名函數進行當即執行出結果。這樣函數參數按值傳遞,至關於在這個內部函數中又建立並返回了一個閉包,每一個函數都有本身的參數,能夠返回各自的值。瀏覽器
另外關於this,因爲匿名函數執行環境具備全局性,this一般指向window。每一個函數在被調用時候,會自動取得兩個變量:this arguments。閉包函數只會搜索到自身活動對象上,不可能直接訪問外部函數中的這兩個變量。所以閉包
var name="haha"函數
var object={this
name:"hehe";spa
getName:function(){return function(){this.name;}}//這裏的this指向window設計
};code
object.getName()();//haha對象
二、閉包有什麼好處呢內存
1)但願一個變量長期駐紮在內存中
2)能夠避免全局變量的污染
三、閉包須要注意的地方
閉包在ie閱覽器下很容易引起內存泄漏。頁面跳轉的時候,變量不進行釋放,一直存在內存中,使得cpu累加提升,只有關閉瀏覽器的時候纔會釋放。
window.onload = function(){ |
var oDiv = document.getElementById('div1'); |
//一個對象屬性引用一個內部函數,而這個內部函數又去引用外部對象,就會出現內存泄漏問題 |
oDiv.onclick = function(){ |
alert(oDiv.id); |
}; |
//解決辦法 |
window.onunload = function(){ |
oDiv.onclick = null; |
}; |
}; |
另外一種作法: |
window.onload = function(){ |
var oDiv = document.getElementById('div1'); |
var id = oDiv.id; //提早創建變量 |
oDiv.onclick = function(){ |
alert(id); |
}; |
oDiv = null; //是對象爲空 |
}; |