前言

JS 中的垃圾回收算法有两个版本:

在 c 语言中,内存的申请、使用和释放(内存生命周期)每一步都是开发者控制;在自动 gc 的语言中,例如 js 中,开发者只感知内存的使用。

引用计数算法

简单说:如果对象被其它对象引用,那么就不能被垃圾回收。

原理:每个对象有个属性值,来标识它被引用的次数。为 0 的时候,可以垃圾回收。

例如:

let a = {
    key1: {
        name: "test",
    },
};

// 现在,a被b引用
// a的key1属性被c引用
let b = a;
let c = a.key1;

b = null; // 释放a的一个引用,但是不能被回收,因为c还引用了a.key1
c = null; // a不被任何对象引用,被垃圾回收

引用计数缺陷

引用计数有个问题,当“循环引用”的时候,无法回收内存。

例如:

function f() {
    let a = {};
    let b = {};
    // a, b循环引用
    a.key1 = b;
    b.key1 = a;
}

// 函数本身也是个对象,它被a和b引用
// 而a和b都互相被引用,没法被垃圾回收
f();

标记清除算法

原理:假定设置一个叫做根(root)的对象(在 Javascript 里,根是全局对象)。垃圾回收器将定期从根开始,找所有从根开始引用的对象,然后找这些对象引用的对象……从根开始,垃圾回收器将找到所有可以获得的对象和收集所有不能获得的对象。

step1: 从根开始寻找

https://tva1.sinaimg.cn/large/007S8ZIlgy1gjtn2kx5xbj30jw0ah761.jpg

step2: DFS 找到被引用的对象。

https://tva1.sinaimg.cn/large/007S8ZIlgy1gjtn2wh7z3j30ju0ae761.jpg

Powered by Fruition