Javascript 为什么在InternetExplorer8中会出现此漏洞?
为什么下面的代码会泄漏Javascript 为什么在InternetExplorer8中会出现此漏洞?,javascript,internet-explorer,memory-leaks,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 wrappedListe
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.
}
问题在于事件(几乎总是在Internet Explorer中,顺便说一句)
看看并注意它是如何收集垃圾的
附加事件时,您正在创建循环引用。请在中阅读更多信息。代码泄漏是因为您调用attachEvent不正确-Microsoft坚持事件名称为标准DHTML事件 如果将
'eventName'
更改为'click'
,则不会泄漏
一个更可靠的解决方案是,将事件附加代码更改为检查DomeElement中的
'on'+eventname
,如果这是错误的,则拒绝附加事件。我知道IE过去有一个错误,它会对本机对象和javascript对象使用单独的垃圾收集,所以,每当您在javascript对象和本机对象之间形成一个循环时,垃圾收集器都无法清理它。是吗?我认为item指向item.elem,这是一个具有返回item的处理程序的div。-与您的问题不太相关,但您可以通过使用listener.apply(item,arguments)
来消除self
变量。:-)完全地但这实际上是我编写的一个类的一个简化版本,在这个类中addEvent方法无法如此方便地访问实例-因此var self=thisOpening post已经用问题的解决方案更新了!是的,因为函数在闭包中捕获对DOM元素的引用,所以当JScript对其进行垃圾收集时,DOM元素会泄漏。是吗?@Pointy:是的,这都是关于事件处理程序的作用域,或者更确切地说是关于该作用域中捕获的DOM引用:)我知道IE的循环引用相关内存泄漏。然而,这里的要点是,我要特别删除事件处理程序。这不应该破坏循环引用吗?@jordancpaul:出于某种原因,ie不理解垃圾收集处理程序是可以的,或者更具体地说,当您删除它时,它的作用域是可以的。这在ie中已经有很长一段时间了。。。请阅读以下内容:我已经用更多的评论更新了我原来的帖子,更好地说明了我为什么感到困惑。
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.