隨著 Web 應用復雜程度越來越高,以及 NodeJS 大規模投入生產環境,許多 Web 應用都會長時間運行, JAVAScript 的內存管理顯得更為重要。
JavaScript 具備自動回收垃圾的機制, 執行環境會負責管理代碼在執行環境過程中使用的內存,將某些不再被使用的的變量所占用的內存釋放掉,正因如此,大多數情況我們在前端開發的時候,并不是那么關注我們的頁面用了多少內存,是否合理,需不需要優化。
JavaScript 基礎中有很多重要的知識點是和內存相關的,比如深拷貝和淺拷貝、閉包、原型、引用數據類型和引用傳遞等。
當然,關于 JS 的內存空間和內存相關的知識已經有很多專業的文章解釋的很詳細了,這里就不再贅述了。
比如關于 JS 內存空間的知識可以看看:內存空間詳細圖解
關于內存周期和垃圾回收的知識可以閱讀參考 MDN 的文章,其他文章無外乎也是根據這個來介紹的:Memory_Management
關于 JavaScript 內存泄漏也可以看一下阮一峰老師的文章 JavaScript 內存泄漏教程
在 Web 應用開發中,我們應該注意:
1. 避免沒有必要全局變量的使用
前端開發者都知道,在局部作用域中,當函數執行完畢,局部變量也就沒有存在的必要了,它很容易被垃圾回收器回收,當使用全局變量定義值時,垃圾回收器,很難判斷全局變量需要什么時候釋放內存空間,因此是不會去對其進行回收銷毀的。而該變量會一直存在老生代堆內存中,直到頁面被關閉。
function setName () { name = "alloy"; } // 等價 function setName () { window.name = "alloy" }
另外一種意外情況是;
function setName (name) { this.name = name; } setName("alloy")
我們可以在 JS 文件的開頭通過添加"use strict" 開啟嚴格的解析模式,來避免一些意外創建的全局變量。
2. 及時解除引用
如果必須要一個全局變量來存儲大量數據,那么請確保在用完之后將其賦值為 null。
delete 操作符用于刪對象的某個屬性;如果沒有指向這個屬性的引用,那它最終會釋放。
但注意的一點是,盡量不要在需要密集運算的函數中去使用 delete,這很可能會引發瀏覽器在不恰當的時候的 GC,和其他語言一樣,JavaScript 的 GC 策略無法避免 GC 時停止響應其他操作,而 JavaScript 的 GC 在 50ms 甚至以上,對普通應用還好,如果是對于操作頻繁的 Web 應用或者游戲來說,就比價煩惱了。
const Room = { desks: 10, chairs: 22 }; console.log(Room.desks); // 10; delete Row.desks; console.log(Room.desks); // undefined
有時候我們雖然用 removeChild 移除了 button,但是還在 node 對象里保存著 #button 的引用,DOM 元素還在內存里面,需要及時解除引用。
var node = { button: document.getElementById('button'); }; document.body.removeChild(document.getElementById('button'));
3. 減少對象的創建
垃圾回收周期性運行,如果分配的內存非常多,或者新建很很多實例的話,那么回收工作也會很辛苦。
盡量避免在經常調用的方法中循環使用 new 對象,而且還要花時間對這些對象進行垃圾回收和處理。
設計模式中的享元模式就是為了減少對象的多次創建而來的。在我們可以控制的范圍內,最大限度的重用對象。
4. 內存不是緩存
緩存在需求開發中舉足輕重,但是很多時候我們會把許多大數據緩存在內存中,導致我們的內存占用始終處于高位,內存對任何程序開發都是寸土寸金 的,若果不是很重要的資源,請不要直接放在內存中,或者制定過期機制,自動銷毀過期緩存。
5. 避免復雜的遞歸調用;
通常情況下,簡單的遞歸調用還不至于導致堆棧溢出,但遇到復雜且每次調用需要 在棧里存儲大量信息的時候,成千上萬個此類空間累積起來,很容易就超過了棧空間。
6. 合理使用的 IndexedDB
其實這個是和 JS 關系不是很大,但是對于 Web 應用的影響卻十分重要,曾經我遇到過一個用戶案例,由于長時間的本地數據寫入,和一些上報日志沒有被及時清除,導致用戶的瀏覽器中對應域名下的 IndexedDB 存儲高達 12GB,瀏覽器在訪問對應域名的時候,也可以初始化 IndexedDB 和讀取本地存儲的數據,而面對如此龐大的數據,瀏覽器內存暴漲,最后崩潰,避免過度依賴 IndexedDB,無腦寫入數據而不做定期清理。
總結
這篇分享主要總結了我們在 Web 應用,可能會遇到的一些情況和注意的事情。
很多時候只要我們在編碼的時候多加注意,可以避免很多問題。
希望本文能幫助到您!
點贊+轉發,讓更多的人也能看到這篇內容(收藏不點贊,都是耍流氓-_-)
關注 {我},享受文章首發體驗!
每周重點攻克一個前端技術難點。更多精彩前端內容私信 我 回復“教程”!希望本文能幫助到您!
轉載自AlloyTeam:http://www.alloyteam.com/2019/07/13858/