JS 的垃圾回收机制(Gc机制)

引用

垃圾回收算法主要依赖于引用的概念。在内存管理的环境中,一个对象如果有访问另一个对象的权限(隐式或者显式),叫做一个对象引用另一个对象。例如:一个JavaScript对象具有对它原型的引用(隐式引用)和对它属性的引用(显式引用)。

引用计数垃圾收集

这是最初级的垃圾收集算法。此算法把“对象是否不再需要”简化定义为“对象有没有其他对象引用到它”。如果没有引用指向该对象(零引用),对象将被垃圾回收机制回收。

示例

let o = {
     a: {
        b: 2
     }
};
// 两个对象被创建,一个作为另一个的属性被引用,另一个被分配给变量o
// 显然,两个都不可以被垃圾收集

let o2 = o;   // o2 变量是第二个对这个对象的引用
o = 1;   // 现在,这个对象的原始引用o被o2替换了

let oa = o2.a;  // 引用这个对象的a属性
                       // 现在,这个对象有两个引用了,一个是o2,一个是oa

o2 = "yo"; // 最初的对象现在已经是零引用了,他可以被垃圾回收了
                // 它的属性a的对象还在被oa引用,所以还不能回收

oa = null; // a属性的那个对象现在也是零引用了
               // 它可以被垃圾回收了

限制:循环引用

该算法有一个限制:无法处理循环引用。例:两个对象被创建,并互相引用,形成一个循环。它们被调用之后会离开函数作用域,所以它们以及没有用了,可以被回收了。然而,引用计数算法考虑到它们互相都有至少一次引用,所以它们不会被回收。

function f() {
    let o = {};
    let o2 = {};
    o.a = o2;// o 引用 o2
    o2.a = o;// o2 引用 o
    return "Dobby";
}
f();

IE6,7使用 引用计数方式 对DOM对象进行垃圾回收。

标记-清除算法

这个算法把“对象是否不再需要”简化为“对象是否可获得”。

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

这个算法比前一个算法好,因为“有零引用的对象”总是不可获得的,相反却不一定,比如“循环引用”。

从2012年起,所有现代浏览器都使用了标记-清除垃圾回收算法。所有对JavaScript垃圾回收算法的改进都是基于标记-清除算法的改进,并没有改进标记-清除算法本身和它对“对象是否不再需要”的简化定义。

限制:那些无法从根对象查询到的对象都将被清除

尽管这是一个限制,但实践中我们很少会碰到类似的情况,所以开发者不太会去关心垃圾回收机制。

参考:内存管理 - JavaScript | MDN

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容