个人简介
👀个人主页: 前端杂货铺
🙋♂️学习方向: 主攻前端方向,正逐渐往全干发展
📃个人状态: 研发工程师,现效力于中国工业软件事业
🚀人生格言: 积跬步至千里,积小流成江海
🥇推荐学习:🍍前端面试宝典 🎨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
- 内存泄漏