LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

[点晴永久免费OA]内存泄漏——海量数据背后隐藏的项目生产环境崩溃风险!如何避免内存泄漏

zhenglin
2025年9月6日 10:15 本文热度 108
内存泄漏(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 的垃圾回收机制和闭包原理,可以更有意识地优化代码,避免性能隐患。



阅读原文:原文链接


该文章在 2025/9/6 10:31:40 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2025 ClickSun All Rights Reserved