美文网首页程序员让前端飞
【js】浅析js垃圾回收机制

【js】浅析js垃圾回收机制

作者: 陈小俊先生 | 来源:发表于2017-07-24 17:33 被阅读0次

    引言:对于 C 语言这般的低级语言,一般可以通过比如 malloc() 和 free()可以在内存中释放我们定义的变量。但是JavaScript的垃圾回收是自动进行的,那么js在何时回收变量呢?


    首先来看一下内存的生命周期:

    1. 分配你所需要的内存
    2. 使用分配到的内存(读、写)
    3. 不需要时将其释放\归还

    所以,我们只要知道js引擎怎么判断内存变量不再需要,就知道js是在什么时候回收内存变量了。

    我们先来说一种古老的垃圾回收机制:

    引用计数垃圾收集

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

    我们看一段代码来分析:

    // 两个对象被创建,一个作为另一个的属性被引用,另一个被分配给变量o
    // 很显然,没有一个可以被垃圾收集
    var o = { 
      a: {
        b:2
      }
    }; 
    
    // o2变量是第二个对“这个对象”的引用
    var o2 = o; 
    
    // 现在,“这个对象”的原始引用o被o2替换了
    o = 1;      
    
    // 引用“这个对象”的a属性
    // 现在,“这个对象”有两个引用了,一个是o2,一个是oa
    var oa = o2.a; 
    
    // 最初的对象现在已经是零引用了
    // 他可以被垃圾回收了
    // 然而它的属性a的对象还在被oa引用,所以还不能回收
    o2 = "yo"; 
    oa = null; 
    // a属性的那个对象现在也是零引用了
    // 它可以被垃圾回收了
    

    引用计数垃圾收集有一个很大的缺陷:无法处理循环引用

    比如,无法处理下列代码:

    function f(){
      var o = {};
      var o2 = {};
      
      // o 引用 o2
      o.a = o2; 
    
      // o2 引用 o
      o2.a = o; 
    }
    
    f();
    

    其实,引用计数垃圾收集 是古老的IE 6, 7 采用的垃圾手机机制,去他喵的IE6,7

    接下来我们介绍一个更现代化的垃圾收集机制:

    标记-清除垃圾收集

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

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

    这个算法比前一个要好,因为“有零引用的对象”总是不可获得的,但是相反却不一定。怎么理解呢?比如这段引用计数没法回收的代码:

    function f(){
      var o = {};
      var o2 = {};
      
      // o 引用 o2
      o.a = o2; 
    
      // o2 引用 o
      o2.a = o; 
    }
    
    f();
    // 定期从window对象开始,o和o2不可获得,回收
    

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

    相关文章

      网友评论

        本文标题:【js】浅析js垃圾回收机制

        本文链接:https://www.haomeiwen.com/subject/qknbkxtx.html