接上回我写了一篇关于闭包的博客《学习JavaScript之闭包》, 最后谈到闭包导致的问题时留了一个尾:
在IE9以下的浏览器中会有内存泄漏的问题。
今天的博客就继续探索一下内存泄漏的问题。
浅谈JavaScript垃圾回收机制
1.标记清除
一开始垃圾收集器会给内存中的所有变量做一个标记,之后当程序运行进入相应的环境时,会去掉环境中的变量和被环境中变量引用的变量标记;当退出该环境后,无法再被访问的变量又重新被标记,这些被重新标记的变量就会被垃圾收集器回收。
2.引用计数
记录每个值被引用的次数,当被引用次数为0时该值才会被回收。如果某个值被其他对象引用(赋给某个变量),引用次数+1;如果不再被引用则-1。
闭包导致的内存泄漏怎么产生的
在IE9以前的浏览器中,DOM对象的垃圾回收机制就是使用引用计数(虽然JS引擎是用标记清除),因此一旦产生循环引用(比如下面这个例子)内存就会一直被占用而无法回收。
function a () {
var div = document.getElementById('myTitle')
div.onclick = function () {
alert(div.id)
}
}
这段代码中变量div中保存了一个HTML元素对象,又创建了一个事件处理程序,其中还直接引用了div.id形成了循环引用,而且这个匿名函数只要存在就能利用闭包的特性访问到div,因此这个HTML元素的引用至少是1。
如何解决内存泄漏的问题
首先要解除循环引用:把div.id赋值给一个变量,然后在匿名函数中引用该变量,因为变量只包含值而不存在对div直接引用,所以解除了循环引用。但是,由于闭包的特性使得其仍保存着a函数的活动对象(等于间接地在引用HTML元素),因此还需要手动解除div对HTML元素的引用。用代码写出来就是:
function a () {
var div = document.getElementById('myTitle')
var id = div.id // 解除循环引用
div.onclick = function () {
alert(id)
}
div = null // 手动解除闭包对外部函数活动对象的引用
}
这样DOM对象的引用就变成了0,也就会被正常地回收了。
博客地址:lbj的前端之路
原文链接:学习JavaScript之内存泄漏
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。