js内存泄露的几乎栽意况详细探索

内存泄露是依同一块被分配的内存既非可知下,又休可以回收,直到浏览器进程截止。在C++中,因为凡手动管理内存,内存泄露是平日出现的事体。而现行风行的C#及Java等语言使用了全自动垃圾回收措施管理内存,正常使用的意况下几不会晤有内存泄露。浏览器中呢是应用电动垃圾回收措施管理内存,但由于浏览器垃圾回收措施有bug,会发生内存泄露。

1、当页面中元素被移除或互换时,若元素绑定的轩然大波仍尚未给移除,在IE中不会师作出确切处理,此时假诺先期手工移除事件,不然会是内存泄露。 

复制代码代码如下:

<div id=”myDiv”> 
<input type=”button” value=”Click me” id=”myBtn”> 
</div> 
<script type=”text/javascript”> 
var btn = document.getElementById(“myBtn”); 
btn.onclick = function(){ 
document.getElementById(“myDiv”).innerHTML = “Processing…”; 

</script> 

诺改成为下边 

ECMAScript,复制代码代码如下:

<div id=”myDiv”> 
<input type=”button” value=”Click me” id=”myBtn”> 
</div> 
<script type=”text/javascript”> 
var btn = document.getElementById(“myBtn”); 
btn.onclick = function(){ 
btn.onclick = null; 
document.getElementById(“myDiv”).innerHTML = “Processing…”; 

</script> 

抑或使用事件委托 

复制代码代码如下:

<div id=”myDiv”> 
<input type=”button” value=”Click me” id=”myBtn”> 
</div> 
<script type=”text/javascript”> 
document.onclick = function(event){ 
event = event || window.event; 
if(event.target.id == “myBtn”){ 
document.getElementById(“myDiv”).innerHTML = “Processing…”; 


</script> 

2、 

复制代码代码如下:

var a=document.getElementById(“#xx”); 
var b=document.getElementById(“#xxx”); 
a.r=b; 
b.r=a; 

复制代码代码如下:

var a=document.getElementById(“#xx”); 
a.r=a; 

对此纯粹的
ECMAScript 对象而言,只要没任何对象引用对象
a、b,也就是说它们只是互相的援,那么仍旧会被垃圾收集连串识别并拍卖。不过,在
Internet Explorer 中,假诺循环引用中的其他对象是 DOM 节点或者 ActiveX
对象,垃圾收集系统尽管未会面发觉它们中的循环关系和网遭到之此外对象是割裂的连释放它们。最后她将为保留在内存中,直到浏览器关闭。 
3、 

复制代码代码如下:

var elem = document.getElementById(‘test’); 
elem.addEventListener(‘click’, function() { 
alert(‘You clicked ‘ + elem.tagName); 
}); 

登时段代码把一个匿名函数注册也一个DOM结点的click事件处理函数,函数内援了一个DOM对象elem,就形成了闭包。这即会发一个循环引用,即:DOM->闭包->DOM->闭包…DOM对象在闭包释放前不会晤吃放走;而闭包作为DOM对象的事件处理函数存在,所以当DOM对象释放前闭包不晤面释放,固然DOM对象在DOM
tree中删去,由于这一个轮回引用的在,DOM对象与闭包都不谋面于释放。可以据此底的主意好避这种外存泄露 

复制代码代码如下:

var elem = document.getElementById(‘test’); 
elem.addEventListener(‘click’, function() { 
alert(‘You clicked ‘ + this.tagName); // 不再直接引用elem变量 
}); 

4、 

复制代码代码如下:

function bindEvent() 

var obj=document.createElement(“XXX”); 
obj.onclick=function(){ 
//Even if it’s a empty function 

闭包分外容易构成循环引用。如若一个结缘闭包的函数对象被指定为,比如一个
DOM
节点的事件处理器,而针对性该节点的援又于指定为函数对象效率域中的一个运动(或可变)对象,那么尽管有一个循环引用。 
DOM_Node.onevent
-<function_object.[[scope]] -<scope_chain
-<Activation_object.nodeRef -<DOM_Node。 

变异如此一个巡回引用是不难的,而且有些浏览一下含类似循环引用代码的网站(平常会冒出于网站的每个页面被),就会见耗费大量(甚至整个)系统内存。 
解决之道,将事件处理函数定义在表面,解除闭包 

复制代码代码如下:

function bindEvent() 

var obj=document.createElement(“XXX”); 
obj.onclick=onclickHandler; 

function onclickHandler(){ 
//do something 

或当概念事件处理函数的标函数中,删除对dom的援(题外,《JavaScript权威指南》中介绍了,闭包中,效用域中尚无因而的性质可以去,以缩减内存消耗。) 

复制代码代码如下:

function bindEvent() 

var obj=document.createElement(“XXX”); 
obj.onclick=function(){ 
//Even if it’s a empty function 

obj=null; 

5、 

复制代码代码如下:

a = {p: {x: 1}}; 
b = a.p; 
delete a.p; 

实践及时段代码之后b.x的价值依然是1.由于已经去除的性引用依旧留存,因而在JavaScript的一些实现着,可能因这种无审慎的代码而致内存泄露。所以在销毁对象的当儿,要全套历属性中属性,依次删除。 
6.
机动型装箱转换 
别无相信,下边的代码在ie体系中会晤招内存泄露 

复制代码代码如下:

var s=”lalala”; 
alert(s.length); 

s本身是一个string而非object,它没有length属性,所以当访问length时,JS引擎会自动创制一个现String对象封装s,而此目的自然会漏风。这多少个bug匪夷所思,所幸解决起来优良好,记得有着值类型做.运算在此之前先显式转换一下: 

复制代码代码如下:

var s=”lalala”; 
alert(new String(s).length); 

7、某些DOM操作 

IE类其余故意问题
简单的来说就是是于通往非在DOM树上的DOM元素appendChild;IE7中,貌似为了精益求精内存泄露,IE7拔取了太的缓解方案:离开页面时回收所有DOM树上的元素,其余一概不任。

初稿链接:http://www.jb51.net/article/37685.htm