微信号:FrontDev

介绍:分享 Web 前端相关的技术文章、工具资源、精选课程、热点资讯

JavaScript内存泄露

2015-07-15 19:57 前端大全

(点击上方,可快速关注)


英文:Memory leaks

译者:韩子迟

网址:http://www.cnblogs.com/zichi/p/4571051.html


译者前言


原文地址:Memory leaks


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


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


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


JavaScript的内存管理


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


下面再举个GC的例子:


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)


内存结构如下:




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


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


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



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


function setHandler() {


var elem = document.getElementById('id')


elem.onclick = function() {


// ...

}


}

dom元素elem通过onclick引用了一个function,而这个function内部也能引用外部作用域里的dom变量elem。



甚至onclick函数里没有代码,该循环引用同样成立。而一些像addEventListener/attachEvent的方法也会形成类似的循环引用。


内存泄露


当一个对象不再被引用,但是浏览器由于某些原因并没有释放内存,这时就会引起内存泄露。浏览器问题,浏览器的插件问题,或者我们自己的代码问题都可能引起内存泄露。


在前面垃圾回收机制一文中我们了解,在IE8以下时,dom对象的循环引用就会引起内存泄露(更进一步讲,其实是COM对象)


function setHandler() {

var elem = document.getElementById('id')

elem.onclick = function() {

/* ... */

}

}


dom对象外,任何的COM对象包括XMLHttpRequest都会引起内存泄露。


IE的内存泄露的解决方式是打破循环引用。



我们把dom元素elem赋值为null,所以onclick里的function不会再引用elem,所以这个循环被打破了。


关于XmlHttpRequest的内存管理和泄露:


以下的代码在IE9以下完美泄露…


var xhr = new XMLHttpRequest()

// or ActiveX in older IE


xhr.open('GET', '/server.url', true)


xhr.onreadystatechange = function() {

if(xhr.readyState == 4 && xhr.status == 200) {


// ...

}

}


xhr.send(null)


让我们来看看内存树:



JQuery中针对内存泄露的措施以及新的泄露


jQuery这块还没仔细研究过,略…


在chrome开发者工具栏中,有个timeline,能或多或少检测内存泄露。





前端大全

微信号:FrontDev

打造东半球最好的 前端技术 微信号

--------------------------------------

商务合作QQ:2302462408

招聘和猎头服务QQ:2302462408

投稿网址:top.jobbole.com





 
前端大全 更多文章 5个典型的JavaScript面试题(上) Limu:JavaScript的那些书 Web开发:我希望得到的编程学习路线图 JavaScript基础工具清单 常用排序算法之JavaScript实现
猜您喜欢 一款快速生成代码的Xcode插件FastStub 12款优秀的开源报表工具介绍 【UXRen活动现场笔录】走不出“交互设计”的产品经理不是好的英语老师 今晚19点LIVE开播~ 干货 ▏程序员知道这些事情就离成功不远了!