据我了解,javascript 中的内存管理是通过引用计数来完成的——虽然对对象的引用仍然存在,但它不会被释放。这意味着在单页应用程序中创建内存泄漏是微不足道的,并且可能会绊倒那些来自 java 背景的用户。这不是特定于 JQuery。以如下代码为例:
function MyObject = function(){
var _this = this;
this.count = 0;
this.getAndIncrement = function(){
_this.count++;
return _this.count;
}
}
for(var i = 0; i < 10000; i++){
var obj = new MyObject();
obj.getAndIncrement();
}
在您查看内存使用情况之前,它看起来很正常。由于“_this”指针(增加 i 的最大值以更显着地看到它),当页面处于活动状态时,MyObject 的实例永远不会被释放。 (在旧版本的 IE 中,它们在程序退出之前永远不会被释放。)由于 javascript 对象可能在框架之间共享(我不建议尝试这样做,因为它非常容易受到影响。),即使在现代浏览器中,也有一些情况下 javascript物体的停留时间可能比它们预期的要长。
在jquery的上下文中,经常会存储引用来节省dom搜索的开销——例如:
function run(){
var domObjects = $(".myClass");
domObjects.click(function(){
domObjects.addClass(".myOtherClass");
});
}
由于回调函数中对它的引用,这段代码将永远保留 domObject(及其所有内容)。
如果 jquery 的编写者在内部错过了这样的实例,那么库本身就会泄漏,但更多的时候是客户端代码。
第二个例子可以通过在不再需要时显式清除指针来修复:
function run(){
var domObjects = $(".myClass");
domObjects.click(function(){
if(domObjects){
domObjects.addClass(".myOtherClass");
domObjects = null;
}
});
}
或再次查找:
function run(){
$(".myClass").click(function(){
$(".myClass").addClass(".myOtherClass");
});
}
一个好的经验法则是在定义回调函数时要小心,并尽可能避免过多的嵌套。
编辑:正如 Erik 在 cmets 中指出的那样,您还可以使用 this 指针来避免不必要的 dom 查找:
function run(){
$(".myClass").click(function(){
$(this).addClass(".myOtherClass");
});
}