JavaScript 的垃圾回收机制

垃圾回收机制是JavaScript中自动释放内存的机制,避免内存泄露导致系统性能下降。主要策略包括标记清除和引用计数,前者是当前浏览器的主流方法,后者可能导致循环引用的问题。内存管理优化建议包括及时解除不再使用的引用,使用const和let声明变量以促进早期垃圾回收。理解垃圾回收的触发条件和策略对于避免性能问题至关重要。
摘要由CSDN通过智能技术生成

1、什么是垃圾回收机制,它是用来做什么的?

  1. 总所周知,内存这玩意是有限的,我们在 JavaScript 中创建对象,函数等一切都在占用内存,如 果不进行清理的话,迟早会 “内存泄露” ,后果就是影响系统性能,严重的直接造成系统崩溃。
    综上所述,这个时候就出现了我们的主角“垃圾回收机制”,帮助我们在变量不使用的时候自动将其内存释放。

  2. 在我们创建变量的时候 Js 会自动帮其分配内存,而垃圾回收机制就是 不定时性 的去帮我们清理掉那些不再使用变量。

  3. 垃圾回收机制是自动进行回收操作的,好处是:使得我们开发人员不用过多去关注内存问题。坏处:垃圾回收机制如同我们的函数,总有一个触发条件,当我们不了解它的时候,总是去触发它,那么会给我们的程序带来严重的性能问题!

  4. 用一句话来形容其作用就是:当内存不再被需要使用时帮我们释放掉。

2、垃圾回收机制的触发条件与性能问题。

  1. 比如 IE (曾经的噩梦级副本),它在 IE7 之前的策略是根据分配数,比如分配了256个变量,4096个对象/数组,或者64kb的字符串。只要满足其中某个条件,就会触发垃圾回收程序。所以会导致如果有一个脚本中含有过多的变量,在整个生命周期一直保持有前面垃圾回收程序触发条件临界值的数量的变量,就会频繁的触发垃圾回收,使性能受到严重的影响。

  2. IE7 发布后,JavaScript 引擎被调优为动态改变分配变量,字面量或数组等会触发垃圾回收程序的阈值。IE7 和 IE6 的初始阈值都是一样的。动态在于:如果垃圾回收程序的内存不到已分配 15%,那么阈值就会翻倍。但是如果有一次阈值达到 85%,阈值将会变为默认值。

注意点:在某些浏览器中是有主动触发垃圾回收的,但是不推荐主动回收(至于为啥,俺也不知道,后续看到相关答案再来更新)。

3、垃圾回收机制的主要的标记策略。

  • 标记清理(目前浏览器的主流策略)

    可以理解为,在不定期的垃圾回收程序启动的时候,会将所有变量打上一个标记,然后再去上下文对象中查询正在被引用的变量,删除它们的标记,那么这个时候还有标记的变量,就是等待被删除的变量,原因是上下文中的变量都没有访问它们。随后垃圾回收程序会做一次“内存清理”,销毁带标记的所有变量并回收它们的内存。

  • 引用计数(小部分浏览器保留,不常用)

    可以理解为,对每个变量都记录它被引用的次数,如果被引用则次数++,如果保存该引用的变量被其他值覆盖,那么引用–。最后如果值的引用数为0,说明该值已经无关注的必要,那么可以安全无痛的回收其内存了~

  • 问题场景:

循环引用

function fn(){
    let objectA = new Object();
    let objectB = new Object();
    objectA.childObj = objectB;
    objectB.fatherObj = objectA;
    //此时 objectA 和 objectB 因为互相引用所以的引用计数都为 2
}

在“标记清除”的策略场景下,这两个对象在函数结束之后,都不在作用域中,所以会被回收。但是在引用计数中,他们在函数结束后还会存在,因为他们的引用数永不为0。如果该函数被调用,那么会导致大量的内存永不释放。
正确的做法应该是这种写法:

function fn(){
    let objectA = new Object();
    let objectB = new Object();
    objectA.childObj = objectB;
    objectB.fatherObj = objectA;
    
    objectA = null;
    objectB = null;
    //这个时候回切断变量与之前引用值之间的关系!
}

4、内存管理(优化)。

  • 在 JavaScript 中,我们虽然不用关注内存管理。不过,我们得先了解一个计算机基础,系统给浏览器分配的可操控内存会比给桌面软件分配的更少,分配给移动端浏览器的就更少了。至于为什么会这样呢,更多是出于安全性的考虑,为了避免运行大量的 JavaScript 的网页耗尽了系统内存而使得系统崩溃。
    所以我们虽然不用关注,但是将内存的占用量保持在一个较小的值,会有利于性能的提升。
    解除引用
    在数据不必要的时候,我们可以将它的值设为 null ,从而等待下一次垃圾回收将其释放。

  • 通过 const 和 let 声明提高性能(还没了解到这里的朋友可以看看我的另外一篇)
    因为 ES6 新增的这两个关键字不仅有助于改善代码风格(var 声明的变量难找… 曾经被jsp支配的恐惧),而且因为 const 和 let 因为其块级作用域的原因,相比于使用 var ,可能更早的被垃圾回收器给收走,释放内存。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值