javascript内存管理详细解析(2)


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

  return "azerty";
}

f();
// 两个对象被创建,并形成相互引用
// 函数调用结束之后,他们不会脱离函数作用域,虽然他们不会被使用,但不会被释放
// 这是因为,引用计数的算法判定只要对象存在被引用的情况,那么就不能对其执行垃圾回收


现实中的例子
ie6、7中,在dom对象上使用引用计数的算法,这里会存在内存泄露的问题。

复制代码 代码如下:


var div = document.createElement("div");
div.onclick = function(){
  doSomething();
}; // div 通过 click 属性引用了事件处理程序
// 当事件处理函数中访问了div变量的时候,会形成循环引用,将导致两个对象都不会被回收,造成内存泄露


标记 - 清除算法

他引入了“对象不再需要”和“对象不可访问(对象不可达)”的概念。该算法假设有一系列的根对象(javascript中的根对象就是全局对象),每隔一段时间,垃圾收集器就会从根对象开始,遍历所以他引用的对象,然后再遍历引用对象引用的对象,以此类推。使用这种方式,垃圾收集器可以获得所有可访问的对象,回收那些不可访问的对象。

这种算法比之前的算法好些,0引用的对象会被设置为不可访问对象,同时他也避免了循环引用造成的困恼。

截止2012年,大多数现代浏览器使用的是这种“标记-清除算法”的垃圾回收器。JavaScript垃圾收集领域(代/增量/并发/并行的垃圾收集),在过去的几年改善了与之相关的算法,但是垃圾收集算法本身(标记-清除算法)和“如何判定一个对象不再需要”并没有得以改善。

周期不再是一个问题

在第一个例子中,函数调用结束之后,这两个对象不会被全局对象引用,也不会被全局对象引用的对象引用。因此,他们会被javascript垃圾回收器标记为不可访问对象。这种事情同样也发生在第二个例子中,当div和事件处理函数被垃圾回收器标记为不可访问,他们就会被释放掉。

限制:对象需要明确的标记为不可访问

这种标记的方法存在局限,但是我们在编程中被没有接触到他,所以我们很少关心垃圾回收相关的内容。

您可能感兴趣的文章:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wdzydf.html