轉:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/A_re-introduction_to_JavaScriptjavascript
使用閉包的一個壞處是,在 IE 瀏覽器中它會很容易致使內存泄露。JavaScript 是一種具備垃圾回收機制的語言——對象在被建立的時候分配內存,而後當指向這個對象的引用計數爲零時,瀏覽器會回收內存。宿主環境提供的對象都是按照這種方法被處理的。java
瀏覽器主機須要處理大量的對象來描繪一個正在被展示的 HTML 頁面——DOM 對象。瀏覽器負責管理它們的內存分配和回收。瀏覽器
IE 瀏覽器有本身的一套垃圾回收機制,這套機制與 JavaScript 提供的垃圾回收機制進行交互時,可能會發生內存泄露。數據結構
在 IE 中,每當在一個 JavaScript 對象和一個本地對象之間造成循環引用時,就會發生內存泄露。以下所示:閉包
function leakMemory() { var el = document.getElementById('el'); var o = { 'el': el }; el.o = o; }
這段代碼的循環引用會致使內存泄露:IE 不會釋放被 el
和 o
使用的內存,直到瀏覽器被完全關閉並重啓後。函數
這個例子每每沒法引發人們的重視:通常只會在長時間運行的應用程序中,或者由於巨大的數據量和循環中致使內存泄露發生時,內存泄露才會引發注意。this
不過通常也不多發生如此明顯的內存泄露現象——一般泄露的數據結構有多層的引用(references),每每掩蓋了循環引用的狀況。code
閉包很容易發生無心識的內存泄露。以下所示:對象
function addHandler() { var el = document.getElementById('el'); el.onclick = function() { el.style.backgroundColor = 'red'; } }
這段代碼建立了一個元素,當它被點擊的時候變紅,但同時它也會發生內存泄露。爲何?由於對 el
的引用不當心被放在一個匿名內部函數中。這就在 JavaScript 對象(這個內部函數)和本地對象之間(el
)建立了一個循環引用。blog
這個問題有不少種解決方法,最簡單的一種是不要使用 el
變量:
function addHandler(){ document.getElementById('el').onclick = function(){ this.style.backgroundColor = 'red'; }; }
另一種避免閉包的好方法是在 window.onunload
事件發生期間破壞循環引用。不少事件庫都能完成這項工做。注意這樣作將使 Firefox 中的 bfcache 沒法工做。因此除非有其餘必要的緣由,最好不要在 Firefox 中註冊一個onunload
的監聽器。