← 返回目录

第 9 卷

第 9 / 10 卷日期:

原因:未使用`var/let/const`声明的变量,会被默认挂载到浏览器的`window`对象或Node.js的 `global`对象上。全局对象的引用会一直存在直到程序终止,导致这些变量对应的内存无法被回收。

示例:

Code block

1function handleData() {

2//遗漏let/const,data成为全局变量(window.data)
3data = { list: new Array(100000) };
4//函数执行完后,data仍被window引用,无法回收
5}
6handleData();
  1. 闭包引用未及时释放

原因:闭包会永久保留外部函数的作用域,若闭包被长期引用(如作为全局变量、事件回调),则外部函数中的变量/对象会被持续持有,即使外部函数执行完毕,这些变量也无法被GC回收。

示例:

Code block

1function createClosure() { 2// 大对象,占用大量内存

3const largeObj = new Array(1000000).fill(0);
4return function() {
5//闭包引用largeObj,导致其无法回收
6console.log(largeObj.length);
7};
8}
9//全局变量长期引用闭包
10const persistentClosure = createClosure();
  1. 未移除的事件监听

原因:为DOM元素、`window`、`EventEmitter`(Node.js)绑定的事件监听,若元素被移除、组件销毁或业务逻辑结束后,未通过`removeEventListener`移除监听,监听函数及它引用的所有对象

会被持续持有,无法回收。

示例(浏览器):

4} 5// 绑定事件

6btn.addEventListener('click', clickHandler);
7//移除DOM元素,但未移除事件监听
8document.body.removeChild(btn);
9// clickHandler仍被事件系统引用,无法回收
  1. 未清理的定时器/计时器

原因:`setTimeout`、`setInterval`创建的定时器,若不再需要但未通过`clearTimeout`、 `clearInterval`清理,定时器的回调函数及引用的对象会被浏览器/Node.js的事件循环持续引用,导

致内存无法释放。尤其是`setInterval`,会重复执行并持续占用内存。

示例:

Code block

1const userData = { name: '张三', age: 25 };
2//定时器回调引用userData
3const timer = setInterval(() => {
4console.log(userData.name);
5}, 1000);
6//业务结束后未清理定时器,userData和timer均无法回收
  1. 僵尸DOM(DOM元素引用丢失)

原因:DOM元素被JS变量引用,当该DOM元素从页面中移除后,JS变量未被清空,仍持有DOM元素的引用。此时DOM元素同时被JS和DOM树引用(移除后DOM树引用消失,但JS引用仍存在),导致

DOM对象无法被GC回收,成为“僵尸DOM”。

示例:

Code block

1// 引用DOM元素

2let container = document.getElementById('container');
3//移除DOM元素
4document.body.removeChild(container);
5//未清空JS引用,container仍指向DOM对象,导致其无法回收

示例:

Code block

1function fetchData() {

2const largeData = new Array(1000000);
3return new Promise((resolve) => {
4//未调用resolve,Promise长期pending,largeData被持续引用
5// resolve(largeData);
6});
7}
8//调用后未处理,largeData无法回收
9fetchData();
  1. 无限制的内存缓存

原因:使用对象、Map、WeakMap以外的结构作为内存缓存时,若未设置缓存过期时间、未限制缓存大小,数据会持续累积,占用的内存无法被回收,最终导致内存泄漏。

示例:

Code block

1// 无清理机制的缓存对象 2const cache = {};

3// 持续向缓存添加数据,无上限 4function setCache(key, value) {

5cache[key] = value;

6} 7// 业务运行中不断调用,缓存越来越大,内存无法释放

  1. Node.js特有的内存泄漏

除上述通用场景外,Node.js中还有专属泄漏场景:

  • 未关闭的文件句柄(`fs.open`后未调用`fs.close`);
  • 未关闭的网络连接(TCP/UDP/WebSocket连接未销毁);
  • `EventEmitter`重复绑定事件且未移除,导致引用累积;
  • 子进程(`child_process`)未正常退出,持续占用资源。
全站分卷索引 · 10 卷
  1. 1第 1 卷
  2. 2第 2 卷
  3. 3第 3 卷
  4. 4第 4 卷
  5. 5第 5 卷
  6. 6第 6 卷
  7. 7第 7 卷
  8. 8第 8 卷
  9. 9第 9 卷
  10. 10第 10 卷