• 浅谈浏览器垃圾回收机制


    浅谈浏览器垃圾回收机制

    0.2952019.02.18 17:23:20字数 1,158阅读 6,844
    一、垃圾回收机制原理

       由于字符串、对象和数组没有固定大小,所有当他们的大小已知时,才能对他们进行动态的存储分配。JavaScript程序每次创建字符串、数组或对象时,解释器都必须分配内存来存储那个实体。只要像这样动态地分配了内存,最终都要释放这些内存以便他们能够被再用,否则,JavaScript的解释器将会消耗完系统中所有可用的内存,造成系统崩溃。

    二、垃圾回收原理浅析

      现在各大浏览器通常用采用的垃圾回收有两种方法:标记清除、引用计数。
    1、标记清除(mark and sweep)
      大部分浏览器以此方式进行垃圾回收,当变量进入执行环境(函数中声明变量,执行时)的时候,垃圾回收器将其标记为“进入环境”,当变量离开环境的时候(函数执行结束)将其标记为“离开环境”,在离开环境之后还有的变量则是需要被删除的变量。标记方式不定,可以是某个特殊位的反转或维护一个列表等。
      垃圾收集器给内存中的所有变量都加上标记,然后去掉环境中的变量以及被环境中的变量引用的变量的标记。在此之后再被加上的标记的变量即为需要回收的变量,因为环境中的变量已经无法访问到这些变量。

    关于这一块,建议读读Tom大叔的几篇文章,关于作用域链的一些知识详解,读完差不多就知道了,哪些变量会被做标记。

    2、引用计数

      另一种不太常见的垃圾回收策略是引用计数。引用计数的含义是跟踪记录每个值被引用的次数。当声明了一个变量并将一个引用类型赋值给该变量时,则这个值的引用次数就是1。相反,如果包含对这个值引用的变量又取得了另外一个值,则这个值的引用次数就减1。当这个引用次数变成0时,则说明没有办法再访问这个值了,因而就可以将其所占的内存空间给收回来。这样,垃圾收集器下次再运行时,它就会释放那些引用次数为0的值所占的内存。
    该方式会引起内存泄漏的原因是它不能解决循环引用的问题:

    function sample(){
        var a={};
        var b={};
        a.prop = b;
        b.prop = a;
    }
    

    这种情况下每次调用sample()函数,a和b的引用计数都是2,会使这部分内存永远不会被释放,即内存泄漏。

    低版本IE中有一部分对象并不是原生JS对象。例如,其BOM和DOM中的对象就是使用C++以COM(Component Object Model)对象的形式实现的,而COM对象的垃圾收集机制采用的就是引用计数策略。

    因此即使IE的js引擎是用的标记清除来实现的,但是js访问COM对象如BOM,DOM还是基于引用计数的策略的,也就是说只要在IE中设计到COM对象,也就会存在循环引用的问题。

    当一个DOM元素和一个原生的js对象之间的循环引用时:

    var ele = document.getElementById("eleId");
    var obj = {};
    obj.property = ele;
    ele.property = obj;
    添加 obj.property = null;ele.property = null;即可解除原生JS对象与DOM元素之间的连接。
    

    当闭包中创建循环引用时:

    window.onload = function outerFunction(){
        var obj= document.getElementById("eleId");
        obj.onclick = function innerfunction(){
            console.log(obj.id);
        }
    }
    

    上面这个代码创建了一个作为obj元素处理程序的闭包,而这个闭包则又创建了一个循环引用。obj引用了document.getElementById("element"),而document.getElementById("ele  Id")的onclick方法会引用包括 obj 以内的外部环境中的变量,所谓“外部环境”包括了包含函数的整个活动对象,所以一定会包括 obj(即使闭包没有对 obj 进行直接的引用,例如上文程序中没有 obj.id 出现,包含函数的活动对象(obj)中也依旧会保存一个引用)。

    可以改成下面这个:

    window.onload = function outerFunction(){
        var obj= document.getElementById("element");
        var id = obj.id;//将obj副本保存于变量id中,则不会使obj元素处理程序的闭包创建循环引用
        obj.onclick = function innerfunction(){
            console.log(id);
        }
        ele = null;//手动断开 obj 对 document.getElemengById("element")的引用
    }
    

    介于js的垃圾回收机制,则建议如果当引用完大的对象后将其置为null。

  • 相关阅读:
    PHP开发学习门户改版效果图投票
    怎样用js得到当前页面的url信息方法(JS获取当前网址信息)
    java 获取当期时间之前几小时的时间
    超人学院Hadoop大数据技术资源分享
    plsql导入一个目录下全部excel
    UML简单介绍
    Mod in math
    父母之爱子,则为之计深远是什么意思?_百度知道
    2014创客118新年大爬梯_活动行-国内最好的活动报名及售票平台!
    北京创客空间 BEIJING MAXPACE的小站
  • 原文地址:https://www.cnblogs.com/sexintercourse/p/16603517.html
Copyright © 2020-2023  润新知