js 垃圾回收机制

js中的内存回收

在js中,垃圾回收器每隔一段时间就会找出那些不再使用的数据,并释放其所占用的内存空间。

以全局变量和局部变量来说,函数中的局部变量在函数执行结束后这些变量已经不再被需要,所以垃圾回收器会识别并释放它们。而对于全局变量,垃圾回收器很难判断这些变量什么时候才不被需要,所以尽量少使用全局变量。

2.垃圾回收的两种模式

那么垃圾回收器是如何检测变量是否需要的呢,大体上分为两种检测手段,引用计数与标记清除。

引用计数

引用计数的判断原理很简单,就是看一份数据是否还有指向它的引用,如果没有任何对象再指向它,那么垃圾回收器就会回收

引用计数存在一个很大的问题,就是对象间的循环引用,比如如下代码中,对象o1与o2相互引用,即便函数执行完毕,垃圾回收器通过引用计数也无法释放它们。

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

而且循环引用对象序列化的时候会发生问题,比如调用JSON.stringify()对该类对象进行序列化,就会报错: Converting circular structure to JSON.    而序列化需求很常见,比如发起一个ajax请求提交一个对象就需要对对象进行序列化。

针对这种问题的一种解决方案是去除这种循环引用,Douglas Crockford写了一个JSON的扩展包,里面的cycle.js刚好就是用来解决此类问题。
例如:

  var c = JSON.decycle(a)

这样就去除了a对象的循环引用,如果想恢复原本的循环引用对象a,可以调用retrocycle方法

  var a = JSON.retrocycle(c)

 

标记清除

标记清除的概念也好理解,从根部出发看是否能达到某个对象,如果能达到则认定这个对象还被需要,如果无法达到,则释放它,这个过程大致分为三步:

a.垃圾回收器创建roots列表,roots通常是代码中保留引用的全局变量,在js中,我们一般认定全局对象window作为root,也就是所谓的根部。

b.从根部出发检查所有 的roots,所有的children也会被递归检查,能从root到达的都会被标记为active。

c.未被标记为active的数据被认定为不再需要,垃圾回收器开始释放它们。

当一个对象零引用时,我们从根部一定无法到达;但反过来,从根部无法到达的不一定是严格意义上的零引用,比如循环引用,所以标记清除要更优于引用计数。

从2012年起,所有现代浏览器都使用了标记清除垃圾回收算法,但老版本的IE6除外。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值