function bindEvent()
{
var obj=document.createElement("XXX");
obj.onclick=function(){
//Even if it's a empty function
}
}
这个bindEvent执行时100%会发生内存泄露,Someone 可能会问,哪里出现了循环引用? 关于closure和scope chain参与的循环引用比较复杂,此处暂不深入讨论。有一个简单的判断方式:函数将间接引用所有它能访问的对象。obj.onclick这个函数中 可以访问外部的变量obj 所以他引用了obj,而obj又引用了它,因此这个事件绑定将会造成内存泄露。在IBM的文章中介绍了2种方式解决类似的问题一个是obj=null,另一个是把onclick的函数写在bindEvent外,重复人家的我就不说了。简单贴下代码:
function bindEvent()
{
var obj=document.createElement("XXX");
obj.onclick=onclickHandler;
}
function onclickHandler(){
//do something
}
function bindEvent()
{
var obj=document.createElement("XXX");
obj.onclick=function(){
//Even if it's a empty function
}
obj=null;
}
function bindEvent()
{
var obj=document.createElement("XXX");
var var0="OOXX";//Here is a variable
obj.onclick=function(){
alert(var0);//I want to visit var2 here!
}
return obj;//bindEvent must return obj!
}
function bindEvent()
{
var obj=document.createElement("XXX");
var var0="OOXX";//Here is a variable
obj.onclick= onclickBuilder(var0);//想访问谁就把谁传进去!!
return obj;//bindEvent must return obj!
}
function onclickBuilder(var0)//这里跟上面对应上就行了 最好参数名字也对应上
{
return function(){
alert(var0);
}
}
第二个办法,这个来自51js的chpn同学,让obj=null在return 之后执行!!
function bindEvent()
{
try{
var obj=document.createElement("XXX");
var var0="OOXX";//Here is a variable
obj.onclick=function(){
alert(var0);//I want to visit var2 here!
}
return obj;//bindEvent must return obj!
} finally {
obj=null;
}
}
</html>
<head>
<script language="JScript">
function LeakMemory()
{
var hostElement = document.getElementById("hostElement");
// Do it a lot, look at Task Manager for memory response
for(i = 0; i < 5000; i++)
{
var parentDiv =
document.createElement("<div >");
var childDiv =
document.createElement("<div >");
// This will leak a temporary object
parentDiv.appendChild(childDiv);
hostElement.appendChild(parentDiv);
hostElement.removeChild(parentDiv);
parentDiv.removeChild(childDiv);
parentDiv = null;
childDiv = null;
}
hostElement = null;
}
function CleanMemory()
{
var hostElement = document.getElementById("hostElement");
// Do it a lot, look at Task Manager for memory response
for(i = 0; i < 5000; i++)
{
var parentDiv =
document.createElement("<div >");
var childDiv =
document.createElement("<div >");
// Changing the order is important, this won't leak
hostElement.appendChild(parentDiv);
parentDiv.appendChild(childDiv);
hostElement.removeChild(parentDiv);
parentDiv.removeChild(childDiv);
parentDiv = null;
childDiv = null;
}
hostElement = null;
}
</script>
</head>
<body>
<button >Memory Leaking Insert</button>
<button >Clean Insert</button>
<div id="hostElement"></div>
</body>
</html>
而在IE7中,貌似为了改善内存泄露,IE7采用了极端的解决方案:离开页面时回收所有DOM树上的元素,其它一概不管。但是这不仅没起到任何作用,反而使问题变得更加复杂。对这类问题,除了自觉一点绕开这些恶心的东西,多用innerHTML这种无用的建议之外。我想可以通过覆盖document.createElement来略为改善:
function MemoryFix(){
var garbageBox=document.createElement("div");
garbageBox.style.display="none";
document.body.appendChild(garbageBox);
var createElement=document.createElement;
document.createElement=function(){
var obj=Function.prototype.apply.apply(createElement,[document,arguments]);
garbageBox.appendChild(obj);
return obj;
}
}