JS垃圾回收机制

一. 前言

当我们创建对象时,js会在内存空间开辟地址来存放这个对象的内容。随着软件的运行,创建的对象会越来越多,而当新创建的对象不断添加,不再被使用的老对象却没有被及时清理时,内存占用就会越来越多,造成程序的运行缓慢直到崩溃。这个过程就称为内存泄漏(Memory Leak)

二. 垃圾回收算法

垃圾回收(Garbage Collection, 简称GC) 便是起到清理内存中不再用到的资源的手段。在一些编程语言如C++中,程序员需要时刻关注内存使用并在适当的时候手动清理。而在JS中,浏览器会启用一个垃圾回收器,每过一段时间便会寻找不被使用的资源并清理,这个过程是隐藏且自动的。目前前端使用的垃圾回收机制主要有两种:引用计数法标记清除法

2.1 引用计数法(Reference counting)

2.1.1 原理 :

当新变量指向对象时,该对象引用计数+1。当某一变量不再指向该对象时,引用计数-1。当引用计数为0,清理该对象。

function () {
  const a = new Object();
  // Object被创建,被变量a指向,引用计数+1 = 1
  const b = a;
  // 新变量b指向了Object,引用次数+1 = 2
}
// 离开块级作用域,临时变量a,b被清除,Object的引用次数-2 = 0,Object被清除

以图1为例,在function中创建对象以及指向该对象的两个变量,该对象同时被两个变量所引用,因此引用计数为2。图2展示了退出function块级作用域的状态,此时a,b变量都被清除,对于Object的引用自然也被清除,Object没有被任何东西引用,因此接下来会被垃圾回收。

2.1.2 问题:

引用计数法无法处理循环引用问题。

function () {
  const a = new ObjectA();
  const b = new ObjectB();
  // ObjectA, ObjectB被创建,引用计数都为1
  a.object = b;
  b.object = a;
  // ObjectA, ObjectB互相引用,引用次数各+1都为2
}
// 离开块级作用域,临时变量a,b被清除,ObjectA, ObjectB的引用次数各-1 = 1

图3展示了function块内状态,ObjectA,ObjectB除去变量a,b的引用外还有彼此间的一个引用,此时引用计数都为2。而进入图4的状态后,来自临时变量a,b的引用被清除,Object彼此间的引用仍保留。从外部来看,没有任何方法能够访问到这俩Object,但是由于他们的引用计数不为0,因此无法回收掉这块无效占用的内存。

2.2 标记清除法(mark-sweep)

标记清除法的关键字是可达性。在引用计数法最后一个例子中,互相引用的ObjectA和ObjectB无法被外部变量访问,处于不可达状态。与引用计数法通过计算引用次数不同,标记清除法会使得浏览器清空所有不可达的资源。标记清楚法能够很好的解决引用计数法造成的循环引用的问题,因此现阶段大部分主流浏览器都是使用的引用计数法。

2.2.1 原理:

标记清除分为三个阶段:

  1. 给所有进入环境的资源打上标记
  2. 从根(一般指全局变量)开始通过引用链访问所有可达的对象并清除标记
  3. 删除所有仍拥有标记的资源。

三. 链接

 

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值