我发现自己对javascript垃圾收集以及如何最好地鼓励它感到困惑。
我想知道的是与特定模式有关。我对模式本身是一个好主意还是坏主意不感兴趣,我只是对浏览器垃圾收集器如何响应感兴趣,即引用会被释放和收集,还是会导致泄漏。
想象一下这种模式:
TEST = {
init : function(){
this.cache = {
element : $('#element')
};
},
func1 : function(){
this.cache.element.show();
},
func2 : function(){
TEST.cache.element.show();
},
func3 : function(){
var self = this;
self.cache.element.show();
},
func4 : function(){
var element = this.cache.element;
element.show();
}
func5 : function(){
this.auxfunc(this.cache.element);
}
auxfunc1 : function(el){
el.show();
}
func6 : function(){
var el = getElement();
el.show();
}
getElement : function(){
return this.cache.element;
}
}
现在假设在页面加载TEST.init()
被调用;
然后在不同时间调用各种函数。
我想知道的是,如果在初始化时缓存元素或对象或其他任何内容,并在应用程序的整个生命周期中引用它们,以上面显示的方式,会对浏览器垃圾收集器产生正面或负面影响。
有什么区别吗?哪种方法最能鼓励垃圾收集?它们会导致泄漏吗?有没有循环参考?如果是这样的话?
答案 0 :(得分:5)
此代码本身不应导致任何内存泄漏。特别是在现代浏览器中。它只是一个对象,就像你在任何脚本中都有很多其他对象一样。这一切都取决于你引用它的地点,方式和时间。
基本规则是,每当某个对象不再被引用到代码中的任何地方时(直接/通过变量或间接/通过闭包访问范围),GC将标记并滑动。
如果您使用上面的代码,然后将其他内容分配给TEST
,则引用的对象文字可以是GC,如果没有其他变量引用原始对象。
当然,预测JS中的内存泄漏是一门不精确的科学。根据我的经验,它们并不像你想象的那么普通。 Firebug,Chrome的控制台(探查器)和IE调试器可以帮助您顺利完成任务。
前段时间我对这件事进行了更多挖掘resulting in this question。也许一些链接和发现对你有帮助......
如果不是,这里有一些提示可以避免明显的泄漏:
window.onload
==>在IE< 9中泄漏内存,因为全局对象从未完全卸载,因此事件处理程序不是GC')哦,并回答你的评论中的问题:“但是我担心的是,如果我每次调用this.cache.element,它是否在原始缓存的ON TOP函数范围内创建一个新的引用参考哪些不会被垃圾收集?“
答案是不。因为this
将引用TEST
对象,并且init
函数为对象分配属性cahche
,这本身就是另一个对象文字,其中1个属性引用了jQ对象。该属性(cache
)以及可通过该属性访问的所有内容都将存储在内存中,直到您delete TEST.cache
或delete TEST
为止。如果你要在var cahce = {...};
函数返回时创建ini
该对象将被GC,因为变量不能超过其范围,除非你使用闭包并间接暴露某些变量。