function init() {
var bigString = new Array(1000).join('xxx');
var foo = document.getElementById('foo');
foo.onclick = function() {
// 即使`bigString`在任何地方都没有被引用,这可能会创建对`bigString`的闭包!
};
}
Eric Lippert在一段時間前寫了一篇詳細的部落格文章,講述了這個主題(此外還將其與VBScript進行了比較)。更準確地說,他寫了關於JScript的文章,這是微軟自己實作的ECMAScript,儘管與JavaScript非常相似。我想你可以假設大部分行為在Internet Explorer的JavaScript引擎中都是相同的。當然,具體實作會因瀏覽器而異,但我懷疑你可以將一些常見原則應用於其他瀏覽器。
當涉及DOM物件時,要注意循環引用:
JavaScript中的記憶體洩漏模式
請記住,只有在沒有對該物件的活動引用時,才能回收記憶體。這是閉包和事件處理程序的常見陷阱,因為某些JS引擎不會檢查內部函數中實際引用的變量,並且只會保留封閉函數的所有局部變數。
這裡有一個簡單的例子:
一個天真的JS實作無法在事件處理程序存在時收集
bigString
。有幾種解決這個問題的方法,例如在init()
的末尾設定bigString = null
(delete
對於局部變數和函數參數不起作用:delete
從物件中刪除屬性,而變數物件是不可存取的- 在嚴格模式下的ES5甚至會拋出ReferenceError
,如果您嘗試刪除局部變數!)。我建議盡量避免不必要的閉包,如果您關心記憶體消耗。
Eric Lippert在一段時間前寫了一篇詳細的部落格文章,講述了這個主題(此外還將其與VBScript進行了比較)。更準確地說,他寫了關於JScript的文章,這是微軟自己實作的ECMAScript,儘管與JavaScript非常相似。我想你可以假設大部分行為在Internet Explorer的JavaScript引擎中都是相同的。當然,具體實作會因瀏覽器而異,但我懷疑你可以將一些常見原則應用於其他瀏覽器。
引用自該頁面:
垃圾回收的主要目的是讓程式設計師不必擔心他們創建和使用的物件的記憶體管理,儘管當然有時是無法避免的 - 至少對垃圾回收的工作原理有一個大致的了解總是有益的。
歷史註:答案的早期版本中有一個關於
delete
運算子的錯誤引用。在JavaScript中,delete
運算子從物件中刪除屬性,與C/C 中的delete
完全不同。