個人簡介
👀個人主頁: 前端雜貨鋪
🙋?♂?學習方向: 主攻前端方向,正逐漸往全干發展
📃個人狀態: 研發工程師,現效力于中國工業軟件事業
🚀人生格言: 積跬步至千里,積小流成江海
🥇推薦學習:🍍前端面試寶典 🎨100個小功能 🍉Vue2 🍋Vue3 🍓Vue2/3項目實戰 🥝Node.js實戰 🍒Three.js
🌕個人推廣:每篇文章最下方都有加入方式,旨在交流學習&資源分享,快加入進來吧
文章目錄
- 內存泄漏
- 意外的全局變量
- 沒有控制好的閉包
- DOM 泄漏
- 如何避免內存泄漏
內存泄漏
內存泄漏(Memory Leak)是指程序中已動態分配的堆內存由于某種原因 程序未釋放 或 無法釋放,造成 系統內存的浪費,導致程序運行速度減慢甚至系統崩潰等嚴重后果。
意外的全局變量
如下所示代碼,在 test()
回調函數中意外給全局變量賦了值。
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title></head><style>.main-content {margin-top: 100px;text-align: center;}#input {width: 200px;height: 50px;}#result {margin-top: 20px;font-size: 28;color: #2cc62c;}</style><body><div><input type="button" id="input" value="添加全局變量" /><div id="result"></div></div></body><script>const test = () => {for (let i = 0; i < 10000; i++) {this[`name${i}`] = i;}};const button = document.getElementById("input");button.addEventListener("click", function () {test();document.getElementById("result").innerHTML = "Done";});</script>
</html>
沒有控制好的閉包
這個例子中的問題是:
- 每次點擊按鈕,都會創建10000個閉包函數
- 這些閉包被存儲在全局對象 obj 中
- 由于沒有清理機制,每次點擊都會累積更多的閉包,導致內存不斷增長
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title></head><style>.main-content {margin: auto;text-align: center;}#input {width: 200px;height: 50px;}#result {margin-top: 20px;font-size: 28;color: #2cc62c;}</style><body><div class="main-content"><input type="button" id="input" value="添加閉包" /><div id="result"></div></div></body><script>function fn() {return function () {return "hello";};}const obj = {};document.getElementById("input").addEventListener("click", function () {for (let i = 0; i < 10000; i++) {obj[`name${i}`] = fn();}document.getElementById("result").innerHTML = "Done";});</script>
</html>
DOM 泄漏
div 未被移除。
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title></head><style>#container {margin-top: 100px;text-align: center;}#result {margin-top: 20px;font-size: 28;color: #2cc62c;}</style><body><div id="container"><input id="add" type="button" value="add" /><input id="remove" type="button" value="remove" /><div id="wrapper"></div></div></body><script>const wrapper = document.getElementById("wrapper");const removeBtn = document.getElementById("remove");removeBtn.addEventListener("click",function () {const container = document.getElementById("container");container.removeChild(wrapper);},false);const addBtn = document.getElementById("add");addBtn.addEventListener("click",function () {const div = document.createElement("div");div.className = "result";div.innerHTML = "hello";wrapper.appendChild(div);},false);</script>
</html>
如何避免內存泄漏
- 及時清除引用 :當不再需要閉包時,將其設置為null
- 避免大對象 :不要在閉包中引用大型對象,如果必須使用,考慮在使用后解除引用
- 使用弱引用 :在適當的場景使用WeakMap和WeakSet
- 移除事件監聽器 :當不再需要時,使用removeEventListener移除事件監聽器
- 清除定時器 :使用clearTimeout或clearInterval清除不再需要的定時器
- 實現緩存過期機制 :對于緩存的閉包,實現LRU或過期時間機制
- 避免循環引用 :檢查并避免閉包中的循環引用
- 使用開發工具 :利用Chrome DevTools的Memory面板定期檢查內存使用情況
好啦,本篇文章到這里就要和大家說再見啦,祝你這篇文章閱讀愉快,你下篇文章的閱讀愉快留著我下篇文章再祝!
參考資料:
- 百度 · 百科
- DeepSeek:DeepSeek
- Trae · GPT
- 內存泄漏