一个典型的闭包导致的内存泄露,jquery轻松解决

声明:以下内容来自《jQuery基础教程》 第四版,人民邮电出版社。附录A

作者:[美] Jonathan Chaffer Karl Swedberg
翻译:李松峰

觉得该内容很好,可以购买。

旧版本IE中存在一种难以处理的引用循环问题。当一个循环中同时包含DOM元素和

常规JavaScript对象时,IE无法释放任何一个对象——因为这两类对象是由不同的内存管理程序负
责管理的。换句话说,除非关闭浏览器,否则这种循环在IE中永远得不到释放。为此,随着时间
的推移,这可能会导致大量内存被无效地占用。导致这种循环的一个常见原因是简单的事件处理

程序:

代码清单:

$(document).ready(function() {
var button = document.getElementById('button-1');
button.onclick = function() {
console.log('hello');
return false;
};
});


当指定单击事件处理程序时,就创建了一个在其封闭的环境中包含button变量的闭包。而
且,现在的button也包含一个指向闭包(onclick属性自身)的引用。这样,就导致了在IE中
即使离开当前页面也不会释放这个循环。
为了释放内存,就需要断开循环引用,例如在关闭窗口并删除onclick属性(此时必须注意
不要在window及其onunload处理程序间引入新的循环)。另外,也可以像下面这样重写代码来
避免这种闭包:

代码清单:

function hello() {
console.log('hello');
return false;
}
$(document).ready(function() {
var button = document.getElementById('button-1');
button.onclick = hello;
});


因为hello()函数不再包含button,引用就成了单向的(从button到hello)、不存在的
循环,所以就不会造成内存泄漏了。

用jQuery化解引用循环
下面,我们通过常规的jQuery结构来编写同样的代码:

代码清单:

$(document).ready(function() {
var $button = $('#button-1');
$button.click(function(event) {
event.preventDefault();
console.log('hello');
});
});


即使此时仍然会创建一个闭包,并且也会导致同前面一样的循环,但这里的代码却不会使IE
发生内存泄漏。由于jQuery考虑到了内存泄漏的潜在危害,所以它会手动释放自己指定的所有事
件处理程序。只要坚持使用jQuery的事件绑定方法,就无需为这种特定的常见原因导致的内存泄
漏而担心。
但是,这并不意味着我们完全脱离了险境。当对DOM元素进行其他操作时,仍然要处处留

心。只要是将JavaScript对象指定给DOM元素,就可能在旧版本IE中导致内存泄漏。jQuery只是
有助于减少发生这种情况的可能性。
有鉴于此,jQuery为我们提供了另一个避免这种泄漏的工具。使
用.data()方法可以像使用扩展属性(expando)一样,将信息附加到DOM元素。由于这里的数
据并非直接保存在扩展属性中(jQuery使用一个内部对象并通过它创建的ID来保存这里所说的数
据),因此永远也不会构成引用循环,从而有效回避了内存泄漏问题。无论什么时候,当我们觉
得扩展属性好像是一种方便的数据存储机制时,都应该首选.data()这种更安全可靠的替代
方案。

你可能感兴趣的:(jquery)