JS垃圾回收机制中的引用计数

window.onload = function(){
    var el = document.getElementById("id");
    el.onclick = function(){
        alert(el.id);
    }
}
window.onload=function outerFunction(){
    var obj = document.getElementById("element");
    obj.onclick=function innerFunction(){};
}

这段代码看起来没什么问题,但是obj引用了document.getElementById(“element”),而document.getElementById(“element”)的onclick方法会引用外部环境中的变量,自然也包括obj,请问怎么理解这个两个循环引用?

阅读 3.4k
2 个回答

自己用V8测试了一下,垃圾回收的时候外部环境的作用域并不会全部保留,只会留下函数引用的变量,估计是做了变量分析优化。

obj.onclick=function innerFunction(){}innerFunction函数并没有引用什么。

循环引用类似

  var o = {};
  var o2 = {};
  o.a = o2; // o 引用 o2
  o2.a = o; // o2 引用 o

在使用计数清除法的时候这个变量就永远不会清除掉。以前大多是直接给变量赋值null的方式来清除。

从2012年起,所有现代浏览器都使用了标记-清除垃圾回收算法。
这个算法把“对象是否不再需要”简化定义为“对象是否可以获得”。

这个算法假定设置一个叫做根(root)的对象(在Javascript里,根是全局对象)。定期的,垃圾回收器将从根开始,找所有从根开始引用的对象,然后找这些对象引用的对象……从根开始,垃圾回收器将找到所有可以获得的对象和所有不能获得的对象。

内存管理

看《Node深入浅出》垃圾回收笔记:

clipboard.png

clipboard.png

clipboard.png

这个其实涉及到作用域和闭包的概念,el.onclick和obj.onclick的方法内部其实是一个新的作用域,然后方法实际上是一个outerFunction外部的函数,因为DOM监听事件不可能是局部作用域的,是全局作用域的,这就构成了一个闭包的条件,能够通过外部调用访问函数内部的私有变量,也就是能够访问outerFunction中的变量,因此间接的引用了outerFunction的活动变量中的el,obj变量,除此之外el,obj中的属性onclick指向了匿名函数所在的内存区,这样导致了互相引用循环引用

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题