js垃圾回收机制

1. 垃圾回收机制

简言之,垃圾回收就是把我们不需要再用到的对象释放内存

那怎么判断对象是否不再需要呢

主要有两种方法

  1. 引用计数法
  2. 标记清除法

2. 引用计数法

以前的垃圾回收机制主要是用引用计数法

这种方法判断对象是否不再需要 是通过判断对象是否被引用来实现的

在内存环境里,对象如果被其他对象引用了,说明这个对象我们还需要它,反之则不需要它

注意,这里的对象不只是js对象,也包括函数作用域

看一个例子

// 两个对象被创建
// 1. 一个作为另一个的属性(male)被引用,称之为对象A
// 2. 另一个被分配给变量obj,称之为对象B
var obj = {
    male: {
        age: 20
    }
}

// obj2和obj同时指向对象A
var obj2 = obj
// obj失去对象A的引用(因此也失去了对B的引用)
obj = 1

// p和obj2.male 同时指向对象B 
var p = obj2.male

// obj2失去对象A的引用(因此也失去了对B的引用)
// 现在对象A可以被垃圾回收了
obj2 = null

// 现在对象B可以被垃圾回收了
p = null

但是这种清除方式会存在一个问题,循环引用

o和o2相互引用,因此无法回收。

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

  return "azerty";
}

f();

在IE6,7中,垃圾回收机制采用的是引用计数法,因此会出现内存泄露的情况

例子

var div;
window.onload = function(){
  div = document.getElementById("div");
  div.circularReference = div;
  div.lotsOfData = new Array(10000).join("*");
};

div 这个 DOM 元素里的 circularReference 属性引用了 div,造成了循环引用

因此lotsOfData无法得到释放,内存会一直占着

3. 标记清除法

现在主流浏览器都是使用的标记清除法来作为js的垃圾回收机制

这种方法判断对象是否不再需要 是通过判断对象是否可以到达来实现的

标记清除法算法由标记阶段和清除阶段组成

标记阶段
首先从根(也就是全局对象)开始将可能被引用的对象用递归的方式进行标记,

清除阶段
将没有标记到的对象作为垃圾进行回收。

垃圾收集器建立了一个根节点列表。根节点通常是那些引用被保留在代码中的全局变量。对于 Javascript 而言,Window 对象就是一个能作为根节点的全局变量例子。

垃圾收集器定时运行标记阶段的算法,递归的检查子节点。 下图就是该算法的执行动作

显而易见,全局变量作为根节点是不会被垃圾回收的,平时在开发的过程中,小心使用全局变量

参考文章:
JavaScript 内存管理
JavaScript 内存泄露问题
JavaScript是如何工作的:内存管理 + 如何处理4个常见的内存泄漏(译)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值