目錄
##1 介紹記憶體洩漏(Memory Leaks):是指應用程式已經不再需要的內存,由於某種原因未返回給作業系統或者空閒記憶體池(Pool of Free Memory)。 " > 記憶體洩漏(Memory Leaks):是指應用程式已經不再需要的內存,由於某種原因未返回給作業系統或者空閒記憶體池(Pool of Free Memory)。
3.2 計時器" >3.2 計時器
3.3 多处引用" >3.3 多处引用
3.4 闭包" >3.4 闭包
首頁 web前端 js教程 JavaScript常見幾種的記憶體洩漏

JavaScript常見幾種的記憶體洩漏

Nov 09, 2020 pm 05:31 PM
javascript 內存洩漏

javascript欄位教學介紹常見的記憶體洩漏。

JavaScript常見幾種的記憶體洩漏

  • 前言
  • 1 介紹
  • 2 記憶體洩露的主要原因
  • 3 常見的記憶體洩露
    • 3.1 全域變數
    • 3.2 計時器
    • #3.3 多重引用
    • 3.4 閉包
  • #4 Chrome記憶體分析工具
  • 資料

前言

##在閱讀這篇博客之前,或許需要具備一些JavaScript記憶體管理的知識:

  • V8中JavaScript的記憶體管理與垃圾回收

記憶體洩漏(Memory Leaks):是指應用程式已經不再需要的內存,由於某種原因未返回給作業系統或者空閒記憶體池(Pool of Free Memory)。

記憶體外洩可能帶來的問題:變慢、卡頓、高延遲。

#JavaScript記憶體洩漏的主要原因在於一些不再需要的參考(

Unwanted References

)。 所謂的Unwanted References指的是:有一些內存,其實開發人員已經不再需要了,但是由於某種原因,這些內存仍然被標記並保留在活動根目錄樹中。 Unwanted References就是指這些記憶體的引用。在JavaScript上下文中,Unwanted References是一些不再使用的變量,這些變數指向了原本可以釋放的一些記憶體。

3 常見的記憶體外洩

#3.1 全域變數

首先,我們得知道,JavaScript中的全域變數是由根節點(root node)引用的,因此它們在應用程式的整個生命週期中都不會被垃圾回收。

場景一:在JavaScript中,如果引用未宣告的變量,將會導致,在全域環境中建立新的變數。

function foo(arg) {    
bar = "this is a hidden global variable";
}
登入後複製

上面這串程式碼,實際上如下:

function foo(arg) {   
window.bar = "this is an explicit global variable";
}
登入後複製

假如,我們希望bar這個變數只在foo函數作用域內部使用,但上面這種情況就會意外地在全域作用域內建立bar,這將造成記憶體洩漏。

場景二:

function foo() {    
this.variable = "potential accidental global";
}foo();
登入後複製

同樣的,如果我們希望bar這個變數只在foo函數作用域內部使用,但如果不知道foo函數內部的this指向全域對象,將造成內存洩漏。

建議:

  1. 避免意外地建立全域變數。例如,我們可以使用嚴格模式,則本節的第一段程式碼將會報錯,而不會建立全域變數。

  2. 減少建立全域變數。

  3. 如果必須使用全域變數來儲存大量數據,請確保在處理完數據後將其置null或重新分配。

3.2 計時器

##場景範例:

for (var i = 0; i < 100000; i++) 
{    
var buggyObject = {        
callAgain: function () {            
var ref = this;            
var val = setTimeout(function () 
{                
ref.callAgain();            
}, 10);        
}    
}    
buggyObject.callAgain();    
buggyObject = null;}
登入後複製

3.3 多处引用

多处引用(Multiple references):当多个对象均引用同一对象时,但凡其中一个引用没有清除,都将导致被引用对象无法GC。

场景一:

var elements = 
{    
button: document.getElementById(&#39;button&#39;),    
image: document.getElementById(&#39;image&#39;),    
text: document.getElementById(&#39;text&#39;)};function doStuff() 
{    
image.src = &#39;http://some.url/image&#39;;    
button.click();    
console.log(text.innerHTML);    
// Much more logic}function removeButton() 
{    // The button is a direct child of body.    
document.body.removeChild(document.getElementById(&#39;button&#39;));    
// At this point, we still have a reference to #button in the global    
// elements dictionary. In other words, the button element is still in    
// memory and cannot be collected by the GC.s}
登入後複製

在上面这种情况中,我们对#button的保持两个引用:一个在DOM树中,另一个在elements对象中。 如果将来决定回收#button,则需要使两个引用均不可访问。在上面的代码中,由于我们只清除了来自DOM树的引用,所以#button仍然存在内存中,而不会被GC。

场景二: 如果我们想要回收某个table,但我们保持着对这个table中某个单元格(cell)的引用,这个时候将导致整个table都保存在内存中,无法GC。

3.4 闭包

闭包(Closure):闭包是一个函数,它可以访问那些定义在它的包围作用域(Enclosing Scope)里的变量,即使这个包围作用域已经结束。因此,闭包具有记忆周围环境(Context)的功能。

场景举例:

var newElem;function outer() 
{   
var someText = new Array(1000000);   
var elem = newElem;   
function inner() 
{       if (elem) return someText;  
 }   
 return function () {};
 }setInterval(function ()
  {   newElem = outer();}, 5);
登入後複製

在这个例子中,有两个闭包:一个是inner,另一个是匿名函数function () {}。其中,inner闭包引用了someText和elem,并且,inner永远也不会被调用。可是,我们需要注意:相同父作用域的闭包,他们能够共享context。 也就是说,在这个例子中,inner的someText和elem将和匿名函数function () {}共享。然而,这个匿名函数之后会被return返回,并且赋值给newElem。只要newElem还引用着这个匿名函数,那么,someText和elem就不会被GC。

同时,我们还要注意到,outer函数内部执行了var elem = newElem;,而这个newElem引用了上一次调用的outer返回的匿名函数。试想,第n次调用outer将保持着第n-1次调用的outer中的匿名函数,而这个匿名函数由保持着对elem的引用,进而保持着对n-2次的...因此,这将造成内存泄漏。

解決方案:setInterval中的參數1的程式碼改為newElem = outer()();

這一節內容的具體剖析,可以見資料1和資料2。

4 Chrome記憶體分析工具

#Chrome(最新的86版本)開發者工具中有兩個關於記憶體的分析工具:

  1. Performance

  2. Memory

相關免費學習推薦:javascript(影片)

#

以上是JavaScript常見幾種的記憶體洩漏的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Go 記憶體洩漏追蹤:Go pprof 實作指南 Go 記憶體洩漏追蹤:Go pprof 實作指南 Apr 08, 2024 am 10:57 AM

pprof工具可用於分析Go應用程式的記憶體使用情況和偵測記憶體洩漏。它提供記憶體概況產生、記憶體洩漏識別和即時分析功能。透過使用pprof.Parse產生記憶體快照,並使用pprof-allocspace指令識別記憶體分配最多的資料結構。同時,pprof支援即時分析,並提供端點以遠端存取記憶體使用資訊。

解決閉包導致的記憶體洩漏問題 解決閉包導致的記憶體洩漏問題 Feb 18, 2024 pm 03:20 PM

標題:閉包造成的記憶體洩漏及解決方法引言:閉包是JavaScript中一個非常常見的概念,它可以讓內部函數存取外部函數的變數。然而,閉包在使用不當的情況下可能導致記憶體洩漏。本文將探討閉包所造成的記憶體洩漏問題,並提供解決方法及具體程式碼範例。一、閉包引起的記憶體洩漏問題閉包的特性是內部函數可以存取外部函數的變量,這意味著在閉包中引用的變數不會被垃圾回收。如果使用不當,

簡易JavaScript教學:取得HTTP狀態碼的方法 簡易JavaScript教學:取得HTTP狀態碼的方法 Jan 05, 2024 pm 06:08 PM

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

Golang 技術效能優化中如何避免記憶體洩漏? Golang 技術效能優化中如何避免記憶體洩漏? Jun 04, 2024 pm 12:27 PM

記憶體洩漏會導致Go程式記憶體不斷增加,可通過:關閉不再使用的資源,如檔案、網路連線和資料庫連線。使用弱引用防止記憶體洩漏,當物件不再被強引用時將其作為垃圾回收目標。利用go協程,協程棧記憶體會在退出時自動釋放,避免記憶體洩漏。

如何使用Valgrind檢測記憶體洩漏? 如何使用Valgrind檢測記憶體洩漏? Jun 05, 2024 am 11:53 AM

Valgrind透過模擬記憶體分配和釋放來偵測記憶體洩漏和錯誤,使用步驟如下:安裝Valgrind:從官方網站下載並安裝適用於您作業系統的版本。編譯程式:使用Valgrind標誌(如gcc-g-omyprogrammyprogram.c-lstdc++)編譯程式。分析程式:使用valgrind--leak-check=fullmyprogram指令分析已編譯的程式。檢查輸出:Valgrind將在程式執行後產生報告,顯示記憶體洩漏和錯誤訊息。

C++ 中記憶體洩漏的調試技術 C++ 中記憶體洩漏的調試技術 Jun 05, 2024 pm 10:19 PM

C++中記憶體洩漏是指程式分配了記憶體但忘記釋放,導致記憶體無法被重複使用。偵錯技術包括使用偵錯器(如Valgrind、GDB)、插入斷言和使用記憶體洩漏偵測器函式庫(如Boost.LeakDetector、MemorySanitizer)。透過實作案例展示了使用Valgrind檢測記憶體洩漏,並提出了避免記憶體洩漏的最佳做法,包括:始終釋放分配的記憶體、使用智慧指標、使用記憶體管理庫和定期進行記憶體檢查。

閉包中如何有效避免記憶體洩漏? 閉包中如何有效避免記憶體洩漏? Jan 13, 2024 pm 12:46 PM

如何在閉包中阻止記憶體洩漏的發生?閉包是JavaScript中非常強大的特性之一,它能夠實現函數的巢狀和資料的封裝。然而,閉包也容易導致記憶體洩漏的問題,特別是在處理非同步和定時器的情況下。本文將介紹如何在閉包中阻止記憶體洩漏,並提供具體的程式碼範例。記憶體洩漏通常發生在不再需要某個物件時,卻因為某些原因無法釋放其所佔用的記憶體。在閉包中,當函數引用外部的變量,而這些變量

如何在JavaScript中取得HTTP狀態碼的簡單方法 如何在JavaScript中取得HTTP狀態碼的簡單方法 Jan 05, 2024 pm 01:37 PM

JavaScript中的HTTP狀態碼取得方法簡介:在進行前端開發中,我們常常需要處理與後端介面的交互,而HTTP狀態碼就是其中非常重要的一部分。了解並取得HTTP狀態碼有助於我們更好地處理介面傳回的資料。本文將介紹使用JavaScript取得HTTP狀態碼的方法,並提供具體程式碼範例。一、什麼是HTTP狀態碼HTTP狀態碼是指當瀏覽器向伺服器發起請求時,服務

See all articles