JavaScript 中的内存管理

文章类型:Javascript

发布者:hp

发布时间:2025-04-21

一:引言

JavaScript 内存管理尤其是在构建复杂应用时。如果内存管理不当,可能会导致内存泄漏、性能下降甚至应用崩溃,那么怎么处理呢?

二:定义

内存管理机制主要围绕‌自动内存分配‌和‌垃圾回收‌两大核心

三:类型

(一)内存分配机制

   (1)栈内存(Stack)

       存储‌基本数据类型‌(如 number、string、boolean 等)和‌函数调用上下文‌(如局部变量、参数等)

       系统自动分配和释放,遵循后进先出(LIFO)原则,效率高但容量有限‌

   (2)堆内存(Heap)

       存储‌引用类型数据‌(如对象、数组、函数等),由 JavaScript 引擎动态分配

       变量通过‌内存地址引用堆中的数据‌,需依赖垃圾回收机制释放‌

(二)垃圾回收机制(Garbage Collection, GC)

   (1)‌标记-清除(Mark and Sweep)

           标记阶段‌:从根对象(如 window 或全局对象)出发,递归标记所有可达对象。

           ‌清除阶段‌:回收未被标记的对象内存。该算法能有效处理循环引用问题‌

   (2)‌引用计数

       通过统计对象的引用次数决定是否回收,但无法处理循环引用(如两个对象互相引用)

四:常见泄露场景

1:全局变量未释放

function leak() {
  leakedVar = '这是一个全局变量'; // 意外的全局变量
}

2:未清理的 DOM 引用与事件监听

let element = document.getElementById('myElement');
document.body.removeChild(element); // DOM 元素被移除
console.log(element); // 仍然保留对 DOM 元素的引用

3:闭包长期占用内存

function createClosure() {
  let largeData = new Array(1000000).fill('data');
  return function() {
    console.log(largeData[0]); // 闭包引用了 largeData
  };
}
 
let closure = createClosure();

4:未清除的定时器或回调

let data = fetchData();
setInterval(() => {
  processData(data);
}, 1000);

5:未释放的缓存

let cache = {};
function addToCache(key, value) {
  cache[key] = value;
}

五:常见优化方案

1:使用弱引用:WeakMap 和 WeakSet

let weakMap = new WeakMap();
let key = {};
weakMap.set(key, 'value');
key = null; // key 被回收,weakMap 中的条目也会被清除

2:及时清理资源

let timer = setInterval(() => {}, 1000);
clearInterval(timer); // 清除定时器
 
element.addEventListener('click', handler);
element.removeEventListener('click', handler); // 移除事件监听器

3:优化数据结构

4:使用工具检测内存泄漏

5:分块处理大数据

6:避免频发创建对象