JS記憶體管理實例講解
JS有完善的記憶體處理機制,所以之前我們不用特別的去關注這塊的實作。頁面不快了,刷新一下就好了;瀏覽器卡頓,重啟一下就OK。但是隨著SPA和行動APP的流行,以及未來可能存在的PWA的實現,JS記憶體可能成為新的記憶體瓶頸。
1.什麼是記憶體洩漏
當我們決定不再使用某些記憶體時,由於錯誤的編碼,未能使得GC (Gabbage Collection)正確的將這些記憶體回收的情況,就是記憶體洩漏。
2.記憶體的佔用,分配與回收
2.1 記憶體的佔用
一個物件佔用的記憶體分為直接佔用記憶體(Shallow Size)和占用總記憶體(Retained Size)。
直接佔用記憶體:物件本身所佔用的記憶體。典型的JavaScript物件都會有保留記憶體用來描述這個物件和儲存它的直接值。一般,只有陣列和字串會有明顯的直接佔用記憶體(Shallow Size)。但字串和陣列常常會在渲染器記憶體中儲存主要資料部分,僅在JavaScript物件堆疊中暴露一個很小的包裝物件。
佔用總記憶體:直接佔用記憶體和這個引用的依賴物件所佔用的記憶體。
賦值和New運算都會牽涉到記憶體的佔用。
2.2 記憶體的分配
Chrome V8的垃圾回收(GC)演算法是基於Generational Collection,記憶體被分割為兩種,分別稱為為Young Generation(YG)和Old Generation(OG)。
所謂Young和Old是根據他們所佔用的時間來劃分的。內部存在YG的分配和回收快而頻繁,一般存在的時間很短,所以稱為Young;而在OG中則慢而少發生,所以稱為Old。
因為在V8中,YG的GC過程會阻塞程序,而OG的GC不會阻塞。所以通常開發者會比較關心YG的細節。
YG又平分為兩部分空間,分別稱為From和To。所有記憶體從To空間被分配出去,當To滿時,開始觸發GC,接下來細看一下。
某一時刻,To已經分A、B和C分配了內存,當前它剩下一小塊內存未分配出去,而From所有的內存都空閒著。
此時,一個程式需要為D分配內存,但D所需的記憶體大小超出了To未分配的內存,如下圖。此時,觸發GC,頁面停止執行。
接著From和To進行對換,即原來的To空間被標誌為From,From被標誌為To。並且把活的變數值(例如B)標誌出來,而」垃圾「(例如AC)未被標誌,它們將會被清除。
活的B會被複製到To空間,而「垃圾」AC則被回收,同時,D被分配到To空間,最後成下圖的分佈
至此,整個GC完成,此過程中頁面停止執行,所以要盡可能的快。當YG中的值存活比較久時,它會被推向OG,OG的空間滿時,觸發OG內的GC,OG的GC時會觸發YG的GC。
每次分配都會使To的可用空間減小,程式又更接近GC
#YG的GC會阻塞程序,所以GC時間不宜太長10ms以內,因為16ms就會出現丟幀;GC不宜太頻繁
#某個值變成垃圾後,不會立刻釋放內存,只有在GC的時候所佔內存才會被回收。
2.2 內容皆來自參考文獻
2.3 記憶體的回收
GC Root是記憶體的根結節,在瀏覽器中它是window,在NodeJS中則是global物件。
從GC Root開始遍歷圖,所有能到達的節點稱為活節點,如果存在GC Root無法到達的節點,那麼該節點稱為“垃圾”,將會被回收,如圖中灰色的節點。
至於根節點的回收,不受使用者的控制。
3. 導致記憶體洩漏的原因
#3.1 沒有完全切斷與GC root之間的路徑
因為沒有完全切斷與根節點之間的路徑,導致自動GC不會回收這部分內存,從而造成內存洩漏。
具體的原因有:
#物件之間的相互引用
-
##
<span style="font-size: 14px;">var a, b;<br>a.reference = b;<br>b.reference = a;<br></span>
登入後複製錯誤使用了全域變數
-
#
##DOM元素清空或刪除時,綁定的事件未清除<span style="font-size: 14px;">a = "1234567";<br>相当于<br>window.a = "1234567";<br></span>
登入後複製
<span style="font-size: 14px;"><p id="myp"><br> <input type="button" value="Click me" id="myBtn"><br></p><br><br><script type="text/javascript"><br> var btn = document.getElementById('myBtn');<br> btn.onclick = function () {<br> document.getElementById('myp').innerHTML = 'Processing...';<br> /* 清除事件绑定 */<br> // btn.onclick = null;<br> };<br></script><br></span>
登入後複製
<span style="font-size: 14px;"><p id="myp"><br> <input type="button" value="Click me" id="myBtn"><br></p><br><br><script type="text/javascript"><br> var btn = document.getElementById('myBtn');<br> btn.onclick = function () {<br> document.getElementById('myp').innerHTML = 'Processing...';<br> /* 清除事件绑定 */<br> // btn.onclick = null;<br> };<br></script><br></span>
#閉包引用
- ##
<span style="font-size: 14px;">function bindEvent() {<br> var obj = document.getElementById('xxx');<br><br> obj.onclick = function () {<br> /** 空函数*/<br> };<br><br> /** delete this reference */<br> // obj = null;<br>}<br></span>
DOM元素清空或刪除時,子元素存在JS引用,導致子元素的所有父元素都不會被刪除
<span style="font-size: 14px;">// b是a的子dom节点, a是body的子节点<br>var aElement = document.getElementById("a");<br>var bElement = document.getElementById("b");<br>document.body.removeChild(aElement);<br>// aElement = null;<br>// bElement = null;<br></span>
3.2 過度佔用了記憶體空間
<span style="font-size: 14px;">while(1) {<br> // do sth<br>}<br></span>
<span style="font-size: 14px;">var arr = [];<br>for (var i=0; i< 100000000000; i++) {<br> var a = {<br> 'desc': 'an object'<br> }<br> arr.push(a);<br>}<br></span>
以上是JS記憶體管理實例講解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

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

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

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

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

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

Golang是一門功能強大且高效的程式語言,可用於開發各種應用程式和服務。在Golang中,指標是一種非常重要的概念,它可以幫助我們更靈活和有效率地操作資料。指標轉換是指在不同類型之間進行指標操作的過程,本文將透過具體的實例來學習Golang中指標轉換的最佳實踐。 1.基本概念在Golang中,每個變數都有一個位址,位址就是變數在記憶體中的位置。

JavaScript是一種廣泛應用於Web開發的程式語言,而WebSocket則是一種用於即時通訊的網路協定。結合二者的強大功能,我們可以打造一個高效率的即時影像處理系統。本文將介紹如何利用JavaScript和WebSocket來實作這個系統,並提供具體的程式碼範例。首先,我們需要明確指出即時影像處理系統的需求和目標。假設我們有一個攝影機設備,可以擷取即時的影像數
