最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • JavaScript之垃圾回收机制

    正文概述 掘金(Hzzy)   2021-03-26   376

    JavaScript是如何实现自动回收垃圾机制的?

    它是通过确定哪个变量不会再使用,然后释放它占用的内存。垃圾回收程序不是无时无刻都在运行着,它会每间隔一段时间就会自动运行程序,清除哪些不再使用的内存。

    那是如何检测哪个变量不再使用了呢?

    通过标记清理和引用计数两种方法,可以进行检测哪个变量不再使用,但引用计数方法,在某些场景下却有一些弊端,比如循环引用,下面先讲一下引用计数,之后再讲一下标记清除。

    基于引用策略的垃圾回收程序

    function  b(){
        let obj={
            name:"小黑",
            age:18,
            sex:"男",
        } //对象被引用1次
        return  obj;
    }
    
    let obj=b();
    console.log(obj);
    obj=null;//对象被引用0次,下次执行垃圾回收程序时,会回收引用次数为0的对象
    

    上面的对象最后被引用的次数是1次,为什么不是2次呢?

    因为当函数调用完毕时,函数上下文出栈,函数里的所有变量都会自动被解除引用,所以现在该对象被引用的次数是1,在全局上下文中不会自动地解除对象的引用,如果需要解除引用,需要手动地将变量赋值为null。

    引用计数的垃圾回收策略是有局限性的,来看一下下面的代码

    function a(){
        let obj1=new  Object();
        let obj2=new  Object();
        obj1.a=obj2;
        obj2.a=obj1;
    }
    
    a();
    

    JavaScript之垃圾回收机制

    JavaScript之垃圾回收机制

    当函数a被调用时,函数a的执行上下文被压入执行栈中,然后对函数体里的变量进行变量提升,之后执行代码,变量obj1创建了一个对象(这里给这个对象一个别名叫b,为了后面方便描述),变量obj2也创建了一个对象(别名a),然后obj1的属性a引用了对象obj2,obj2的属性a引用了对象obj1,此时对象a和对象b都被引用了2次。当函数a调用完毕时,函数a释放了它所占用的内存,但是对象a和对象b它们之间互相引用,所以对象a和对象b不会被垃圾回收程序回收内存!这就导致了内存泄漏。

    正是因为引用计数会导致循环引用的问题,现在的垃圾回收程序大多采用标记清理的策略进行垃圾回收!

    基于标记清理的垃圾回收程序

    function a(){
        let name="小黑";
        return name;
    }
    function b(){
        let obj={
            name:"小红",
            age:18,
            sex:"男"
        }
        return  obj;
    }
    
    let c=a();
    
    let d=b();
    
    console.log(name);
    console.log(obj);
    
    

    JavaScript之垃圾回收机制

    JavaScript之垃圾回收机制

    想一想哪个函数会造成内存泄漏?

    函数a中的变量name是原始类型数据(String),当调用函数a时,把字符串的值"小黑"赋值给了变量c,调用完函数a后,函数a释放了它所占用的内存,所以函数a不会造成内存泄漏

    函数b中的变量obj是引用类型(Object),当调用函数b时,将obj的地址值赋值给变量d,调用完函数b后,函数b释放了它所占用的内存,但0x0003的内存却没有被释放,因为全局变量d引用了0x0003,它是一个可达的对象。

    function a(){
        let obj1=new  Object();
        let obj2=new  Object();
        obj1.a=obj2;
        obj2.a=obj1;
    }
    
    a();
    

    JavaScript之垃圾回收机制

    调用函数a完后,全局上下文中没有变量引用它们,所以它们是不可达对象,等下次垃圾回收程序运行时,就会回收它们的内存。

    function a(){
        let obj1=new Object();
        let obj2=new Object();
        obj1.a=obj2;
        obj2.a=obj1;
        return{
            aa:obj1,
            bb:obj2,
        }
    }
    
    var f=a();
    

    JavaScript之垃圾回收机制

    JavaScript之垃圾回收机制

    调用函数a完后,全局上下文中变量f引用了它们,所以它们是可达对象,垃圾回收程序不会回收它们。

    function a(){
        let obj1={
            name:"小黄"
        }
        let obj2={
            name:"小白"
        };
        obj1.a=obj2;
        obj2.a=obj1;
        return{
            aa:obj1,
            bb:obj2,
        }
    }
    
    var f=a();
    f.aa=null;
    

    大家想一想别名为b的对象会不会被垃圾回收程序回收?

    JavaScript之垃圾回收机制

    答案是不会!,可以通过别名为a的对象,到达别名为b的对象,再看下面的代码

    f.bb.a=null;
    

    JavaScript之垃圾回收机制

    当把obj2.a=null时,全局上下文变量f再也到达不了别名为b的对象,所以等下次垃圾回收程序运行时,就会把别名为b的对象进行回收

    到这里,我就把我自己对于垃圾回收机制的理解说完了,有什么不对的地方,欢迎大家指出^^


    起源地下载网 » JavaScript之垃圾回收机制

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元