JavaScript在运行时会自动管理内存,开发者不需要像C语言那样手动申请和释放。但了解内部的堆栈分配与回收策略,对排查内存泄漏和提升性能很有帮助。基本类型如数字、布尔、字符串等通常存放在栈中,而对象、数组、函数等引用类型存放在堆中。
栈内存的分配与回收
栈内存用来存放基本类型值和函数执行上下文。当调用一个函数时,会创建一个栈帧,里面保存局部变量和参数。函数执行结束后,栈帧出栈,对应内存被自动回收,因此栈的分配和释放非常高效。
简单示例
function add(a, b) {
// a和b是基本类型,存放在栈中
let sum = a + b;
return sum;
}
add(1, 2); // 调用结束,栈帧销毁
堆内存的分配与回收
引用类型的数据结构复杂且大小不定,所以放在堆中,栈里只保存指向堆的引用地址。堆内存不会随函数结束自动消失,需要依赖垃圾回收机制来释放不再使用的空间。
引用关系示例
let obj = { name: 'test' }; // obj在栈,对象在堆
let ref = obj; // ref和obj指向同一个堆对象
ref = null; // 断开一个引用,但obj仍引用该对象
常见的垃圾回收策略
引用计数
引用计数记录每个对象被引用的次数,为0时回收。但它无法处理循环引用,容易造成内存泄漏。
function leak() {
let a = {};
let b = {};
a.child = b;
b.parent = a; // 循环引用,引用计数不为0
}
标记清除
现代浏览器主要采用标记清除。从根对象出发,标记所有可达对象,未被标记的视为垃圾并回收,能解决循环引用问题。
| 策略 | 优点 | 缺点 |
|---|---|---|
| 引用计数 | 回收及时 | 循环引用泄漏 |
| 标记清除 | 解决循环引用 | 有停顿开销 |
避免内存泄漏的建议
- 不再使用的对象及时置为
null - 移除无用的事件监听
- 避免意外的全局变量
理解堆和栈的区别以及垃圾回收原理,是写出健壮JavaScript代码的基础。
JavaScript内存管理垃圾回收修改时间:2026-07-26 14:12:39