我有一个内存泄漏,我不明白。我编写了一种机制来处理半自动解除绑定的事件,这应该可以让我轻松地清理内存。但在一种情况下,清理没有发生(我使用chrome的“配置文件(内存堆)”来检查"EventHandler“left的实例)。我真的不明白为什么会这样。封闭式有点奇怪。
see it in action with chrome
function Bind(obj, f) {
return function() {
return f.apply(obj, arguments);
}
}
function EventHandler() {
this.listeners = new Object();
var _listenerID = 0;
this.addListener = function(e, obj, listener, specialDisplay) {
if (typeof(listener) === "function") {
var listenerID = ++_listenerID;
console.log("Events (" + (++EventHandler.All) + ", " + listenerID + ") ++" + e);
if (!this.listeners.hasOwnProperty(e)) {
this.listeners[e] = new Object();
}
this.listeners[e][listenerID] = listener;
if (obj != null && typeof(obj.removeListener) == "function") {
var deleteListenerID = obj.addListener("Delete", null, Bind(this, function() {
this.removeListener(e, listenerID);
obj.removeListener("Delete", deleteListenerID);
}));
}
return listenerID;
}
return null;
}
this.fire = function(e, obj) {
if (this.listeners.hasOwnProperty(e)) {
for(var i in this.listeners[e]) {
this.listeners[e][i](obj);
}
}
}
this.removeListener = function(e, listenerID) {
if (this.listeners.hasOwnProperty(e) && this.listeners[e].hasOwnProperty(listenerID)) {
delete this.listeners[e][listenerID];
console.log("Events (" + (--EventHandler.All) + ", " + listenerID + ") --" + e);
}
}
}
EventHandler.All = 0;
function Loader() {
}
Loader.files = new Object();
Loader.LoadImage = function(src, f) {
if (!Loader.files.hasOwnProperty(src)) {
var handler = new EventHandler();
console.log("Loading.... (" + src + ")");
Loader.files[src] = function(fnct) {
handler.addListener("ImageLoaded", handler, function(img) {
fnct(img);
});
}
handler.addListener("ImageLoaded", handler, function() {
Loader.files[src] = function(fnct) {
fnct(img);
}
});
var img = new Image();
$(img).load(function() {
console.log("Loaded.... (" + src + ")");
handler.fire("ImageLoaded", img);
handler.fire("Delete");
$(img).unbind('load');
});
img.src = src;
}
Loader.files[src](f);
}
Loader.LoadImage("http://serge.snakeman.be/Demo/house.jpg", function() { alert("ok"); });发布于 2013-04-22 00:27:31
您可以创建通过handler变量保存对EventHandler实例的引用的闭包。其中一个闭包在图像加载后仍然存在:
handler.addListener("ImageLoaded", handler, function() {
Loader.files[src] = function(fnct) {
fnct(img);
}
}); 它是内部函数function(fnct) {...。只要闭包存在,就不能释放EventHandler的实例。你唯一的解决方案就是去掉那个闭包。或者,如果可能,您可以手动释放实例。以下内容可能适用于您:
handler.fire("Delete");
handler = undefined;Chrome的内存分析器会向你显示对象的保留树,这只是另一种方式来说“谁持有该对象的引用”。在您的示例中,它是EventHandler <- handler (闭包包含的LoadImage方法的变量) <- house.jpg,它实际上是Loader.files[src],其值为function(fnct) { fnct(img); }。
发布于 2013-04-23 14:58:58
在添加'listeners‘时,如果您长时间使用该查询,请确保将其删除。
this.listeners = new Object();或
this.listeners[e] = new Object();这会将对象作为数组添加到侦听器中,但不会在任何时候删除它们。
这可能是内存消耗的原因。它的对象赋值可能不会泄漏。使用浏览器消耗你的内存。:)
https://stackoverflow.com/questions/15864049
复制相似问题