jor*_*aul 11 javascript internet-explorer memory-leaks
为什么以下代码泄漏?
for (var i = 0; i < 100; i++) {
var item = {};
item.elem = document.createElement('div');
document.body.appendChild(item.elem);
item.addEvent = function(name,listener) {
var self = this;
var wrappedListener = function() {
return listener.apply(self,arguments);
}
//Uh-oh creating a circular reference here!
//The wrappedListener has a closure on self and therefore on item.elem.
addEvent(this.elem,name,wrappedListener);
return wrappedListener;
}
var wrap = item.addEvent('eventName',listen);
//Now remove the eventHandler - this should free up the circular reference.
removeEvent(item.elem, 'eventName', wrap);
if (item.elem.parentNode) {
item.elem.parentNode.removeChild(item.elem);
}
//item.elem = null; //With this also un-commented, the leak disappears.
//The fact that I have to null item.elem tells me that something is holding
//a reference to item, and therefore elem. Setting elem to null fixes the
//problem, but since I am removing the event handler, I don't think this
//should be required.
}
Run Code Online (Sandbox Code Playgroud)
注:addEvent和removeEvent只是抽象attachEvent/ addEventListenerInternet Explorer和其他浏览器之间的差异.
我创建了一个jsFiddle项目来演示这个问题.只需启动Internet Explorer 8并在任务管理器或Process Explorer中查看它.此外,您将看到addEvent和removeEvent那里的定义.
编辑:嗯,我提出了以下解决方案.它不漂亮,但它的工作原理! http://jsfiddle.net/rJ8x5/43/
var item = {};
item.elem = document.createElement('div');
document.body.appendChild(item.elem);
item.addEvent = function(name,listener) {
var wrappedListener = function() {
//Access the scope through the callee properties.
return listener.apply( arguments.callee.scope, arguments);
}
addEvent(this.elem,name,wrappedListener);
//Save the scope not as a closure, but as a property on the handler.
wrappedListener.scope = this
return wrappedListener;
}
var wrap = item.addEvent('eventName',listen);
removeEvent(item.elem, 'eventName', wrap);
//Force the circular reference to GO AWAY.
wrap.scope = null
if (item.elem.parentNode) {
item.elem.parentNode.removeChild(item.elem);
}
//item.elem = null; //No longer needed.
Run Code Online (Sandbox Code Playgroud)
问题是事件(几乎总是在Internet Explorer中,BTW).
看看http://jsfiddle.net/rJ8x5/39/并注意垃圾如何收集罚款.
附加事件时,您正在创建循环引用.阅读更多相关信息在HTML页面上对DOM对象的循环引用会导致内存泄漏.
| 归档时间: |
|
| 查看次数: |
1507 次 |
| 最近记录: |