# 垃圾回收

## 一、引用计数算法

### 1、原理

* 当声明了一个变量b，并且将一个引用类型a赋值给该变量b的时候，a的引用次数就为 1
* 如果a又被赋给另一个变量c，那么引用数加 1
* 如果c的值被其他的值覆盖了，则a的引用次数减 1
* 当a的引用次数变为 0 的时候，说明没有变量在使用，a这个值没法被访问了，垃圾回收器会在运行的时候清理掉引用次数为 0 的值占用的内存

### 2、优点

* 回收的判断标准简单明确：引用数为0就回收

### 3、缺点

* 无法解决循环引用的问题
* 需要维护一个计数器

## 二、标记清除算法

### 1、原理

分为 `标记` 和 `清除` 两个阶段，大致过程：

* 垃圾收集器在运行时会给内存中的所有变量都加上一个标记，假设内存中所有对象都是垃圾，全标记为0
* 然后从各个**根对象**开始遍历，把不是垃圾的节点改成1
* 清理所有标记为0的垃圾，销毁并回收它们所占用的内存空间
* 把所有内存中对象标记修改为0，等待下一轮垃圾回收

### 2、优点

* 实现简单：使一位二进制位（0和1）就可以为其标记

### 3、缺点

* **内存碎片化：**&#x6E05;除之后剩余的对象位置不变而导致的空闲内存不连续
* **分配速度慢：**&#x56E0;为碎片化，内存分配前需要计算，大对象的分配效率会更慢

### 4、解决

**标记整理（Mark-Compact）算法：**&#x6807;记阶段和**标记清除算法**相同；标记结束后，**标记整理算法**会将活着的对象（即不需要清理的对象）向内存的一端移动，最后清理掉边界的内存。可以有效解决**标记清除算法**的弊端。

> 现在大多数浏览器都是基于<mark style="color:green;">**标记清除算法**</mark>

参见：

* <https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Memory_Management>
* <https://juejin.cn/post/6981588276356317214>
