JScript Memory Leaks in Microsoft IE solution 2
正像我上篇文章翻译的一样,Microsoft Internet Explorer 在DOM对象增加事件句柄后会带来内存泄漏的问题。上篇文章也给出了解决方案,但是如果在开发者未知该何时调用这个净化程序时,一般开发者会加入类似的代码:
if ( Nebula.isIE ) {
window.attachEvent("onunload", function () {
Nebula.clearEvent ( document.body );
});
}
这里的Nebula.clearEvent就是上述的净化程序,它在你离开页面或刷新页面时触发,这很重要。比如你正在浏览Gmail,但不知道什么原因导致你必须刷新gmail,这时如果不调用净化程序内存仍然是得不到释放。
是的,你也许也发现了我们传进去的是document.body,这意味着要对整个html文档进行递归地循环地“净化”,效率是很低的。于是我改进了这个方法。
/**
* The basic global namespace
* @constructor
*/
window.Nebula = {
/**
* get the Nebula lib 's version
* @type {string}
*/
version: "1.1.0.0",
/**
* Boolean flag that navigator whether it is MCST IE
* @type boolean
*/
isIE: !!window.ActiveXObject,
/**
* Boolean flag that navigator whether it is Apple Safari
* @type boolean
*/
isSafari: navigator.userAgent.toLowerCase().indexOf("safari") > -1 ,
/**
* Boolean flag that navigator whether it is Opera
* @type boolean
*/
isOpera: navigator.userAgent.toLowerCase().indexOf("opera") > -1 ,
/**
* event names
*/
_eventList: ["onbeforecut", "onblur", "onclick", "oncontextmenu", "oncut",
"ondblclick", "ondeactivate", "ondragenter", "ondragleave", "ondragover",
"ondrop", "onfocus", "onfocusin", "onfocusout", "onhelp", "onkeydown",
"onkeypress", "onkeyup", "onmousedown", "onmouseenter", "onmouseleave",
"onmousemove", "onmouseout", "onmouseover", "onmouseup", "onmousewheel",
"onmove", "onmoveend", "onmovestart", "onpaste", "onreadystatechange",
"onresize", "onresizeend", "onresizestart", "onselectstart"
],
/**
* clear html element 's event handle, fix ie MEMORY LEAKS bug
* @param d , the element of cleared
*/
clearEvent: function (d) {
var a, i, l, n;
if (!d || !this.isIE) {
return;
}
a = this._eventList;
try{
if (a) {
l = a.length;
for (i = 0; i < l; i += 1) {
n = a[i];
if (typeof d[n] === "function") {
d[n] = null;
}
}
}
a = d.childNodes;
if (a) {
l = a.length;
for (i = 0; i < l; i += 1) {
this.clearEvent(d.childNodes[i]);
}
}
}catch(ex){
//alert(ex.message);
}
}
};
if ( Nebula.isIE ) {
window.attachEvent("onunload", function () {
Nebula.clearEvent ( document.body );
});
}
我把DOM元素可能用到event列出来,然后去再去循环这些event,而不是DOM的所有属性。这样好处将会提高效率,减少数万次计算。