JavaScript内存泄露

jopen 9年前

原文出处: Memory leaks   译文出处: 韩子迟   

译者前言

原文地址:Memory leaks

最近简单了解了下JavaScript的闭包和垃圾回收机制(GC),这中间也不得不接触内存泄露这个概念。然后不小心找到了这篇文章,看下来后理解了不少东西,于是译之与大家分享。

在JavaScript中,我们很少考虑到内存管理,但是它又是真实存在的。当我们创建一个变量,接着使用它们,然后浏览器的垃圾回收机制对它们进行回收。

虽然我们很少考虑内存管理,但是当应用程序越来越复杂并且ajax化之后,我们打开一个网页,过段时间发现浏览器消耗的内存不断增大,很有可能是因为内存泄露,这时我们不得不考虑内存管理。

JavaScript的内存管理

JavaScript内存管理的核心也就是JavaScript垃圾回收机制,而存在在内存中的数据包括堆栈中的数据(局部变量,正在被调用的方法的参数)以及全局变量;而对象如果被引用或者存在在一个引用链中时,也会存在在内存中。关于这点可以参考JavaScript垃圾回收机制。

下面再举个GC的例子:

</div>
</div>
</div>
</div>
</div> JavaScript </div> </div>
function Menu(title) { this.title = title this.elem = document.getElementById('id') } var menu = new Menu('My Menu') document.body.innerHTML = '' // (1) menu = new Menu('His menu') // (2)
</tr> </tbody> </table> </div> </div>

内存结构如下:

JavaScript内存泄露

在step(1)后,body.innerHTML被清空了,所以它的子节点都被移除了。但是元素#id是个例外,它依然能通过menu.elem访问,所以它依然存在在内存中,当然如果你无法访问它的父节点,因为它被移除了。

单个的dom元素可能存在在内存中哪怕它的父节点已经被移除。

在step(2)后,window.menu被重新赋值引用,所以原来的menu不可访问了,于是自动被GC回收。

JavaScript内存泄露

而闭包经常会引起循环引用:

1
2
3
4
5
6
7
8
9
10
</div> </td>
function Menu ( title ) {
   this . title = title
   this . elem = document . getElementById ( 'id' )
}
 
var menu = new Menu ( 'My Menu' )
 
document . body . innerHTML = ''    // (1)
 
menu = new Menu ( 'His menu' ) // (2)