Bob*_*mer 15 javascript jquery memory-leaks
许多文章(例如msdn)都说当涉及DOM对象和JS对象时,在某些浏览器中无法清除循环引用.
(IE 6根本无法完成,IE7只能在页面请求之间执行):
Javascript Native(Leaks):
function leak(){
var elem = document.createElement("DIV");
document.body.appendChild(elem);
elem.onclick = function () {
elem.innerHTML = elem.innerHTML + ".";
// ...
};
}
Run Code Online (Sandbox Code Playgroud)
因为元素的onload属性通过闭包引用回自身,所以它创建了一个循环引用:
elem [DOM] -> elem.onclick [JS] -> elem [DOM]
JQuery版本(不泄漏):
function leak(){
var elem = $('<div></div>');
$(document.body).append(elem);
elem.click(function () {
elem.html(elem.html() + ".");
// ...
};
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,即使仍有循环引用,jQuery也会阻止所有相关浏览器中发生泄漏:
elem [JS] -> element [DOM] -> elem.onclick [JS] -> elem [JS]
我的问题:如果仍有循环引用,jQuery如何阻止泄漏?
jQuery代码中的最后一件事(在Sizzle的代码之前,它的选择器引擎)是这个(这是防止泄漏的代码):
// Prevent memory leaks in IE
// Window isn't included so as not to unbind existing unload events
// More info:
// - http://isaacschlueter.com/2006/10/msie-memory-leaks/
if ( window.attachEvent && !window.addEventListener ) {
window.attachEvent("onunload", function() {
for ( var id in jQuery.cache ) {
if ( jQuery.cache[ id ].handle ) {
// Try/Catch is to handle iframes being unloaded, see #4280
try {
jQuery.event.remove( jQuery.cache[ id ].handle.elem );
} catch(e) {}
}
}
});
}
Run Code Online (Sandbox Code Playgroud)
当你在jQuery中做任何事情时,它会存储它所做的事情(即函数)和什么(即DOM元素).onunload通过jQuery缓存从其自己的内部缓存的事件处理程序中移除函数(无论如何都存储事件而不是单个DOM节点).
哦,和行:
if ( window.attachEvent && !window.addEventListener ) {
Run Code Online (Sandbox Code Playgroud)
确保它只在IE上运行.