大家好,我是阿赵。继续学习JavaScript,这次学习一下JavaScript的垃圾回收机制。
一、什么是垃圾回收
之前说过,变量其实是申请用于存放数据的一段内存。我们每次写代码,都会涉及到内存的分配和回收。
内存的生命周期包括:
- 内存分配
- 内存使用
- 内存回收
当某些申请使用了的内存不需要再使用的时候,就需要有一个机制把这部分内存还给系统,这称为垃圾回收机制(Garbage Collection,简称GC)。
JavaScript的内存分配和回收都是自动完成的。内存在不使用的时候会被垃圾回收器自动回收。
如果在程序中分配的内存由于某种原因导致程序未释放或者无法释放,叫做内存泄漏。
二、 堆栈空间分配
内存分为了栈内存和堆内存。
1、 栈(Stack)
定义:栈是一种后进先出(LIFO, Last In First Out)的数据结构,用于存储局部变量和方法调用信息。
位置:通常位于内存的固定区域,由操作系统自动分配和释放。
特点:栈的大小在编译时确定,且一般较小;访问速度快,因为数据连续存储。
用途:主要用于存储函数调用的上下文(如参数、局部变量、返回地址等)。
管理方式:由编译器自动管理,通过压栈(push)和弹栈(pop)操作实现内存的分配和释放。当函数调用结束时,其占用的栈空间会自动被回收。
简单说,栈内存是由操作系统和编译器控制的。
2、 堆(Heap)
定义:堆是用于动态分配内存的区域,程序员可以在运行时请求任意大小的内存块。
位置:不固定的内存区域,由操作系统维护一个空闲内存池供应用程序使用。
特点:堆的大小在运行时动态变化,可以很大;访问速度相对较慢,因为数据可能分散存储在多个地方。
用途:用于存储需要在程序运行期间动态分配和释放的对象或数据结构。
管理方式:由程序员手动管理(或使用智能指针、垃圾收集器等机制)。需要显式地调用内存分配函数(如malloc、new)和释放函数(如free、delete)。
简单说,堆内存是由程序员分配和释放的。
三、 浏览器垃圾回收算法
1、 引用计数法
在之前版本的IE里面采用的一种引用计数的算法。
定义“内存不再使用”是看一个对象是否有指向它的引用,如果没有就回收对象。
这个算法有一个致命的问题,如果是嵌套引用,也就是循环引用,比如对象a引用了对象b,然后对象b里面又引用了对象a。这个情况,尽管a和b都不再使用了,但由于它们各自都有指向自己的引用,所以垃圾回收器并不会去回收对象a和b,就造成了内存泄漏。
2、 清除标记法
现代浏览器大部分已经不再使用引用计数法,而改成了基于标记清除算法的某些改进算法。
清除标记法的核心是:
- 将“不再使用的对象”定义为“无法达到的对象”
- 从根部(JavaScript就是全局变量)出发,定时扫描内存中的对象。凡是能从根部到达的对象都是还需要使用的
- 无法从根本出发触及到的对象,被标记为不再使用,稍后进行回收。

1268

被折叠的 条评论
为什么被折叠?



