内存泄漏到底是个什么东西?如何避免内存泄漏

目录

内存泄漏到底是个什么东西?如何避免内存泄漏

一、什么是内存泄漏?

1、内存泄漏

2、GC(垃圾回收)机制是什么?

二、常见内存泄漏场景

1、意外的全局变量

2、被遗忘的定时器/回调

3、闭包未释放大对象

4、DOM 引用未解绑

 5、被遗忘的监听器、websocket、观察者等(如 IntersectionObserver)

6、缓存未清理(Map / WeakMap 使用不当)

三、结语


        作者:watermelo37

        CSDN万粉博主、华为云云享专家、阿里云专家博主、腾讯云、支付宝合作作者,全平台博客昵称watermelo37。

        一个假装是giser的coder,做不只专注于业务逻辑的前端工程师,Java、Docker、Python、LLM均有涉猎。

---------------------------------------------------------------------

温柔地对待温柔的人,包容的三观就是最大的温柔。

---------------------------------------------------------------------

内存泄漏到底是个什么东西?如何避免内存泄漏

        内存泄漏(Memory Leak)是 Web 开发中常见但容易忽视的问题。随着项目体量增长或长时间运行的单页应用增多,内存泄漏所带来的性能下降、页面卡顿甚至崩溃问题变得尤为突出。

        本文将带你深入理解内存泄漏的成因,常见场景,以及应对方案,助你写出更加稳健高效的前端应用。

一、什么是内存泄漏?

1、内存泄漏

        内存泄漏指的是:程序中某些对象已经不再被需要,但由于某种原因仍然被引用,导致垃圾回收器无法释放这些内存。

2、GC(垃圾回收)机制是什么?

        现代 JavaScript 引擎如 V8 采用 “可达性算法(Reachability)”,当某个对象从根对象(如 window、全局变量、闭包引用等)开始无法被访问到,它就会被回收。

        有些情况下会绕过垃圾回收机制,那些已经不需要但是不会被回收的变量等就会一直保存在内存中,会持续的浪费内存,直到进程被杀死才会彻底清除。这就是内存泄漏产生的原因。

二、常见内存泄漏场景

1、意外的全局变量

        函数内如果不使用 let / var / const 声明变量,就会直接挂载到 window 对象上。所以需要尽量避免直接写变量,或者开始‘ use strict ’严格模式,避免隐式全局变量。

        尽量不要使用 var 定义变量,在全局作用域里面(即函数外)通过 var 定义的变量均会挂载在 window 对象上,不会被销毁,会持续造成内存泄漏。

        尽量使用 const  / let 来定义变量,哪怕是在全局作用域里面通过 const  / let 定义的变量,也只会挂载在 Script 作用域中。即全局词法环境(Lexical Environment) 中,这是一种抽象的作用域管理方式,浏览器自己维护的,你访问不到它,但 JavaScript 引擎知道该怎么找。相比于直接通过 var 挂载到window对象上,相对更好被GC清除一些

function foo() {leaked = "I am global!";
}
foo(); // leaked 被隐式挂载在 window 上

2、被遗忘的定时器/回调

        闭包中的 userData 永远被回调引用,永远不被释放。

const userData = { name: "Tom" };
setInterval(() => {console.log(userData.name); // 闭包引用 userData
}, 1000);

        所以应该在组件销毁时清除定时器。

const timer = setInterval(...);
clearInterval(timer);

3、闭包未释放大对象

        闭包允许函数访问其创建时的作用域链中的变量,即使这些变量在函数外部已经不可访问。闭包会保留对 createClosure 函数作用域链的引用,这意味着 bigData 也会被保留。

function createClosure() {const bigData = new Array(1e6);return function () {console.log('I am using closure');};
}
const closure = createClosure(); // bigData 被保留

        解决方案一般有两种思路,避免大对象进入闭包逻辑:

function createClosure() {const bigData = new Array(1e6); // 创建一个大数组console.log('I am using closure');
}
createClosure();

        或者手动释放引用:

function createClosure() {const bigData = new Array(1e6); // 创建一个大数组return function () {console.log('I am using closure');bigData = null; // 手动释放引用};
}
const closure = createClosure();
closure(); // 调用闭包,释放 bigData

4、DOM 引用未解绑

        DOM 被移除时,如果事件监听没有解绑,闭包可能继续引用 DOM。

const element = document.getElementById('btn');
element.onclick = () => {console.log('clicked');
};

        应在DOM被销毁时及时解绑事件。

element.removeEventListener('click', handler);

 5、被遗忘的监听器、websocket、观察者等(如 IntersectionObserver)

        比如元素删除了,observer 还在监听,需要使用 observer.disconnect() 手动解除观察。

const observer = new IntersectionObserver(() => {console.log('intersected');
});
observer.observe(document.getElementById('foo'));

6、缓存未清理(Map / WeakMap 使用不当)

        Map 会强引用 key 和 value,导致无法释放。致无法释放。

const cache = new Map();
function addToCache(key, value) {cache.set(key, value); // 永久引用
}

三、结语

        内存泄漏的本质是代码“留下来不该留下来的东西”的体现。通过了解 JavaScript 的垃圾回收机制和闭包原理,我们可以更有意识地优化代码,避免性能隐患。

        说实话闭包这个东西,说简单几句话就说完了, 但是要扯到各种作用域,垃圾回收机制,各种作用域创建的函数上下文,可能一万字都讲不清楚,今天就说到这里,有探究想法的读者可以在评论区讨论。

        只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~

        其他热门文章,请关注:

        极致的灵活度满足工程美学:用Vue Flow绘制一个完美流程图

        你真的会使用Vue3的onMounted钩子函数吗?Vue3中onMounted的用法详解

        DeepSeek:全栈开发者视角下的AI革命者

        通过array.filter()实现数组的数据筛选、数据清洗和链式调用

        通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能

        TreeSize:免费的磁盘清理与管理神器,解决C盘爆满的燃眉之急

        通过MongoDB Atlas 实现语义搜索与 RAG——迈向AI的搜索机制

        深入理解 JavaScript 中的 Array.find() 方法:原理、性能优势与实用案例详解

        el-table实现动态数据的实时排序,一篇文章讲清楚elementui的表格排序功能

        前端实战:基于Vue3与免费满血版DeepSeek实现无限滚动+懒加载+瀑布流模块及优化策略

        MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver

        JavaScript中通过array.map()实现数据转换、创建派生数组、异步数据流处理、DOM操作等

        高效工作流:用Mermaid绘制你的专属流程图;如何在Vue3中导入mermaid绘制流程图

        干货含源码!如何用Java后端操作Docker(命令行篇)

        在线编程实现!如何在Java后端通过DockerClient操作Docker生成python环境

        Dockerfile全面指南:从基础到进阶,掌握容器化构建的核心工具

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/452.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【图像处理入门】8. 数学基础与优化:线性代数、概率与算法调优实战

摘要 图像处理的核心离不开数学工具的支撑。本文将深入解析线性代数、概率论在图像领域的应用,包括矩阵变换与图像几何操作的关系、噪声模型的数学描述,以及遗传算法、粒子群优化等智能算法在参数调优中的实践。通过理论结合代码案例,帮助读者掌握从数学原理到工程优化的完…

包含30个APP客户端UI界面的psd适用于旅游酒店项目

包含30个APP客户端UI界面的psd适用于旅游酒店项目 此资源包含30个完全可编辑的psd界面组成。内容包括欢迎页、登录、注册、首页、搜索、侧边菜单、用户中心、个人介绍、用户空间、产品详细信息、酒店预定、天气情况等各种常用界面,您可以将其用于旅游酒店类的APP应用…

华为云Flexus+DeepSeek征文 | 基于华为云ModelArts Studio搭建PandaWiki知识库问答系统

华为云FlexusDeepSeek征文 | 基于华为云ModelArts Studio搭建PandaWiki知识库问答系统 引言一、ModelArts Studio平台介绍华为云ModelArts Studio简介ModelArts Studio主要特点 二、PandaWiki介绍PandaWiki 简介主要特点 三、安装PandaWiki应用一键部署方式访问PandaWiki系统 四…

Python应用八股文

大家好!在 Python 学习的道路上,掌握一些基础知识要点至关重要,这些要点常被称为“Python 八股”。以下是对它们的简易总结,帮助你快速回顾和巩固 Python 的核心概念。 一、数据结构 列表(List):有序可变序…

在 CentOS中安装Docker并安装青龙脚本——笔记

安装依赖 sudo yum install -y yum-utils device-mapper-persistent-data lvm2添加 Docker 官方 GPG 密钥 sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo安装 Docker 引擎 sudo yum install -y docker-ce docker-ce-cli con…

MySQL分库分表面试题深度解析

🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 MySQL分库分表面试题深度解析一、核心概念与…

AI首次自主发现人工生命

转: 近日,人工智能领域迎来了一项革命性的突破。Transformer 论文作者之一的 Llion Jones 与前谷歌研究人员 David Ha 共同创立的人工智能公司 Sakana AI,联合MIT、OpenAI、瑞士AI实验室IDSIA等机构的研究人员,共同提出了一种名为…

企业架构框架深入解析:TOGAF、Zachman Framework、FEAF与Gartner EA Framework

执行摘要 企业架构(EA)是一项至关重要的实践,它使组织能够协调其业务战略、运营流程和技术基础设施,以实现整体战略目标。企业架构框架作为结构化的方法论和综合性工具,旨在管理企业级系统的固有复杂性,提…

[7-01-03].第03节:环境搭建 - 集群架构

RabbitMQ学习大纲 一、使用集群的原因 1.基于以下原因,需要搭建一个 RabbitMQ 集群来解决实际问题 单机版的,无法满足目前真实应用的要求。如果 RabbitMQ 服务器遇到内存崩溃、机器掉电或者主板故障等情况,会导致rabbitMQ无法提供服务单台 R…

基于大模型预测过敏性紫癜的技术方案大纲

目录 一、引言(一)研究背景(二)研究目的二、技术方案(一)数据收集与预处理(二)大模型构建与训练(三)术前预测(四)术中预测与监测(五)术后预测与护理(六)麻醉方案制定(七)统计分析(八)技术验证方法(九)实验验证证据(十)健康教育与指导三、技术方案流程图…

Mysql 忘记密码后如何修改

如果忘记了 Linux 上 MySQL 的 root 密码,可以通过以下步骤重置(适用于 MySQL 5.7+ 及 MariaDB): 步骤 1:停止 MySQL 服务 systemctl stop mysql步骤 2:以跳过权限表的方式启动 MySQL mysqld_safe --skip-grant-tables --skip-networking &此命令会临时禁用密码验证…

从信息孤岛到智能星云:学习助手编织高校学习生活的全维度互联网络

一、项目背景与目标 随着高校信息化建设的推进,大学生在日常学习中对信息获取、时间管理、任务安排等方面的需求日益增长。为了帮助大学生更高效地管理学习生活,我们设计并实现了一个基于 API 调用的学习小助手系统。该系统通过调用外部服务接口&#x…