head
script language = " JScript "
var myGlobalObject;
function SetupLeak() // 产生循环引用,因此会造成内存泄露
{
// First set up the script scope to element reference
myGlobalObject = document.getElementById("LeakedDiv");
// Next set up the element to script scope reference
document.getElementById(" LeakedDiv ").expandoProperty = myGlobalObject;
}
function BreakLeak() // 解开循环引用,解决内存泄露问题
{
document.getElementById( " LeakedDiv " ).expandoProperty = null ;
}
/script
/head
body onload = "SetupLeak()" onunload = "BreakLeak()"
div id = "LeakedDiv" /div
/body
/html
上面这个例子,看似很简单就能够解决内存泄露的问题。可惜的是,当我们的代码中的结构复杂了以后,造成循环引用的原因开始变得多样,我们就没法那么容易观察到了,这时候,我们必须对代码进行仔细的检查。
尤其是当碰到Closure,当我们往Native对象(例如Dom对象、ActiveX Object)上绑定事件响应代码时,一个不小心,我们就会制造出Closure Memory Leak。其关键原因,其实和前者是一样的,也是一个跨javascript object和native object的循环引用。只是代码更为隐蔽,这个隐蔽性,是由于javascript的语言特性造成的。但在使用类似内嵌函数的时候,内嵌的函数有拥有一个reference指向外部函数的scope,包括外部函数的参数,因此也就很容易造成一个很隐蔽的循环引用,例如:
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/webkaifa/)DOM_Node.onevent -function_object.[ [ scope ] ] -scope_chain -Activation_object.nodeRef -DOM_Node。
[http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ie_leak_patterns.asp]有个例子极深刻地显示了该隐蔽性:
html
head
script language = "JScript"
function AttachEvents(element)
{
// This structure causes element to ref ClickEventHandler
// element有个引用指向函数ClickEventHandler()
element.attachEvent("onclick", ClickEventHandler);
function ClickEventHandler(){
// This closure refs element
// 该函数有个引用指向AttachEvents(element)调用Scope,也就是执行了参数element。
}
}
function SetupLeak()
{
// The leak happens all at once
AttachEvents(document.getElementById("LeakedDiv"));
}
/script
/head
body onload = "SetupLeak()" onunload = "BreakLeak()"
div id = "LeakedDiv"/div
/body
/html
猜你喜欢