我试图编写一个带有内存泄漏的javascript代码,以便在Chrome中使用事件探查器。但是,探查器似乎没有显示应有的状态。
这是我的代码:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="start_button">Start</button>
<button id="destroy_button">Destroy</button>
<script type="text/javascript" charset="utf-8">
var Leaker = function(){};
Leaker.prototype = {
init:function(){
this._interval = null;
this.start();
},
start: function(){
var self = this;
this._interval = setInterval(function(){ self.onInterval(); }, 100);
},
onInterval: function(){ console.log("Interval"); }
};
$("#start_button").click(function(){
if(leak !== null && leak !== undefined){
return;
}
leak = new Leaker();
leak.init();
});
$("#destroy_button").click(function(){
leak = null;
});
var leak;
</script>
您可以看到当我单击开始按钮时创建了一个新对象Leaker。
当我单击destroy时,该对象设置为null(注意:由于setInterval仍将起作用,因此不会进行垃圾收集)。
问题:但是,当我使用Google Chrome Profiler时,单击“destroy”后,它没有显示对我的Leaker实例的任何引用(但应显示出这样的引用,因为如上所述,因为setInterval的闭包仍坚持下去)。
单击“销毁”按钮之前的探查器
单击销毁按钮后的探查器(您可以看到我再也找不到泄漏者实例,而它应该在那里)。
在此控制台中,尽管探查器向我们显示不再有Leaker实例,但setInterval仍在起作用。
我在垃圾收集或Chrome分析器的工作方式上缺少什么吗?
最佳答案
这两个事件探查器之间的区别在于,在“销毁” leak
之前,Leaker变量是全局变量,在它之后不是全局变量。因此,只是探查器(和javascript引擎)无法按您的描述方式工作。基本上,您可以看到全局变量,但看不到局部范围的变量。我认为根据范围进行不同分配是有意义的。在将泄漏设置为null之前,其他脚本必须可以使用它。
您可以通过一个最小的示例来查看探查器如何根据作用域进行不同的工作:
var Leaker = function() {};
var Leaker2 = function() {};
// this one is going to be in the profiler
var leak = new Leaker();
(function(){
// this one is not in the profiler
var leak2 = new Leaker2();
setInterval(function(){console.log(leak2)}, 500);
})()
编辑:
为了澄清起见,该对象仍在探查器中,并且仍在分配,但与全局方法不同。我只是创建一个关于Chrome事件探查器如何工作的最小示例。当变量是全局变量时,您将看到它并可以在类过滤器中对其进行过滤,但如果不是,则不能。
现在,它仍然在某个地方,很明显。您可以在闭包下拉菜单中查看,您会看到两个快照上都有一个Leaker:
可能在闭包时创建了重复项,因此也可以分配上下文信息。
关于javascript - Chrome Profiler Javascript内存泄漏,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31673604/