當(dāng)涉及到DOM對(duì)象時(shí),要注意循環(huán)引用:
請(qǐng)記住,只有在沒有對(duì)該對(duì)象的活動(dòng)引用時(shí),才能回收內(nèi)存。這是閉包和事件處理程序的常見陷阱,因?yàn)槟承㎎S引擎不會(huì)檢查內(nèi)部函數(shù)中實(shí)際引用的變量,并且只會(huì)保留封閉函數(shù)的所有局部變量。
這里有一個(gè)簡單的例子:
function init() { var bigString = new Array(1000).join('xxx'); var foo = document.getElementById('foo'); foo.onclick = function() { // 即使`bigString`在任何地方都沒有被引用,這可能會(huì)創(chuàng)建對(duì)`bigString`的閉包! }; }
一個(gè)天真的JS實(shí)現(xiàn)無法在事件處理程序存在時(shí)收集bigString
。有幾種解決這個(gè)問題的方法,例如在init()
的末尾設(shè)置bigString = null
(delete
對(duì)于局部變量和函數(shù)參數(shù)不起作用: delete
從對(duì)象中刪除屬性,而變量對(duì)象是不可訪問的 - 在嚴(yán)格模式下的ES5甚至?xí)伋?code>ReferenceError,如果您嘗試刪除局部變量?。?/p>
我建議盡量避免不必要的閉包,如果您關(guān)心內(nèi)存消耗。
Eric Lippert在一段時(shí)間前寫了一篇詳細(xì)的博客文章,講述了這個(gè)主題(此外還將其與VBScript進(jìn)行了比較)。更準(zhǔn)確地說,他寫了關(guān)于JScript的文章,這是微軟自己實(shí)現(xiàn)的ECMAScript,盡管與JavaScript非常相似。我想你可以假設(shè)大部分行為在Internet Explorer的JavaScript引擎中都是相同的。當(dāng)然,具體實(shí)現(xiàn)會(huì)因?yàn)g覽器而異,但我懷疑你可以將一些常見原則應(yīng)用于其他瀏覽器。
引用自該頁面:
垃圾回收的主要目的是讓程序員不必?fù)?dān)心他們創(chuàng)建和使用的對(duì)象的內(nèi)存管理,盡管當(dāng)然有時(shí)候是無法避免的 - 至少對(duì)垃圾回收的工作原理有一個(gè)大致的了解總是有益的。
歷史注:答案的早期版本中有一個(gè)關(guān)于delete
運(yùn)算符的錯(cuò)誤引用。在JavaScript中,delete
運(yùn)算符從對(duì)象中刪除屬性,與C/C++中的delete
完全不同。