徹底消除 JavaScript 中的記憶體洩漏


垃圾回收語言中記憶體洩漏的主要原因是不必要的引用。為了理解記憶體洩漏,讓我們看看記憶體釋放(垃圾回收)是如何工作的。

標記-清除演算法 −此演算法將“不再需要物件”的定義簡化為“物件不可達”。此演算法假設知道一組稱為根的物件。在 JavaScript 中,根是全域性物件。垃圾回收器會定期從這些根開始,遞迴查詢從這些根引用的所有物件。從根開始,垃圾回收器將找到所有可達物件,並收集所有不可達物件。

記憶體洩漏的型別

1. 全域性變數(未宣告/意外)

在 JS 中,如果您沒有指定宣告關鍵字(let、var、const),則可能會意外地宣告一個全域性變數。JS 向外查詢作用域,直到到達全域性作用域,如果它在任何作用域中都沒有找到該變數,它就會建立一個全域性變數。

示例

function test() {
   a = [1, 2, 3]
}
test()
// a was initialized without declaration using a keyword and is now in the global scope.
console.log(a)

輸出

[1, 2, 3]

這種行為會導致記憶體洩漏,因為變數不知不覺地存在於全域性作用域中,並且除非程式結束,否則不會被釋放。這可以透過使用宣告關鍵字來解決。

2. 閉包

如果在外部函式中宣告的變數會自動提供給巢狀的內部函式,即使在巢狀函式中未使用/引用該變數,它也會繼續保留在記憶體中,則會在閉包中發生記憶體洩漏。

3. 脫離 DOM/DOM 外部引用

DOM 是一個雙向連結串列樹,對樹中任何節點的引用都將阻止整個樹進行垃圾回收。脫離 DOM 或 DOM 外部引用意味著已從 DOM 中移除但透過 JS 保留在記憶體中的節點。這意味著只要在任何地方仍然存在對變數或物件的引用,即使該物件已從 DOM 中移除,也不會進行垃圾回收。一旦完成 DOM 的一部分,務必從 JS 中刪除引用。

4. 事件監聽器

addEventListener() 方法將事件處理程式附加到元素,並且可以將多個事件處理程式新增到單個元素。如果 DOM 元素及其事件監聽器的生命週期不同,則可能會導致記憶體洩漏。

更新於:2019年9月17日

瀏覽量:132

啟動您的 職業生涯

完成課程獲得認證

開始學習
廣告