从我记得的一个不太遥远的过去,Javascript解释器在面对循环引用时遇到了内存泄漏问题。
最新的浏览器仍然如此吗? (例如Chrome,FF 3.5等)
答案 0 :(得分:28)
当您在JavaScript对象和DOM节点等主机对象之间建立引用循环时,我们与JavaScript讨论的绝大多数泄漏都特别在IE6-7中。
在IE6中,这是特别有害的,因为当你离开页面时你没有得到回忆;它一直消失,直到你退出浏览器。在IE7中清除页面现在会返回内存,但是当你有一个长时间运行的应用程序时仍然会遇到困难。 IE8通过将DOM节点转换为本机JavaScript对象而不是主机对象来正确解决大部分问题。 (您仍然可以通过在参考循环中包含其他非本机对象(如ActiveX对象)来触发IE8中的泄漏。)
对于所有浏览器,随机位置肯定会出现小的模糊内存泄漏,特别是在旧版本中。但是没有一种方法可以像IE refloop问题那样轻松地分类和避免它们。
答案 1 :(得分:17)
要添加 bobince 答案,我使用 IE8 进行了一些测试。
我尝试了http://www.javascriptkit.com/javatutors/closuresleak/index.shtml
提供的几乎所有示例除了移除仍然附加有事件的子节点的示例之外,其中没有人会再次泄露内存(至少不是以可察觉的方式)。
这种类型的例子我认为Douglas Crockford在他的queuetest2中有更好的解释。
这个仍然会泄漏IE8上的内存,只需运行the test script并查看Windows任务管理器 - 性能 - PF使用情况,即可轻松测试。你会发现每次循环PF使用量增加了近1MB(非常快)。
但IE8中的内存在页面卸载上发布(例如导航到新页面或重新加载同一页面),显然也是当完全关闭浏览器时。
因此,为了让最终用户能够感知到IE8上的内存泄漏(因为系统性能降低),他需要长时间保持在同一页面上,现在这种情况经常发生在AJAX上,但是这个页面还需要数百个子节点删除附加了事件的元素。
道格拉斯·克罗克福德测试强调浏览器添加 10000个节点然后删除,这非常适合向您展示问题,但在现实生活中我从未有过删除10个以上元素的页面。 INMHO通常使用display: none
而不是删除整个节点集更快,这就是为什么我不使用removeChild
那么多。
对于上面解释的对IE8内存泄漏更感兴趣的人,我做了另一个测试,当使用innerHTML
时,似乎内存泄漏在IE8中根本没有出现appendChild/removeChild
添加/删除附加事件的子元素。所以显然道格拉斯·克罗克福德purge function(由他建议防止IE中的内存泄漏)在IE8中不再需要了,至少在使用innerHTML
时...
(感谢以下4esn0k评论)
...而且道格拉斯·克罗克福德purge function在IE8上根本不起作用,在他的代码var a = d.attributes
中返回NO onclick
属性(或任何其他onevent
属性) IE8上的运行时(它们在IE7上返回)。
“在删除任何元素之前,应该调用清除函数 通过removeChild方法,或者通过 设置 innerHTML 属性。“
我在这里提供测试代码:
<body>
<p>queuetest2 similar to the one provided by Douglas Crockford
at http://www.crockford.com/javascript/memory/leak.html
<br>but this one adds/removes spans using innerHTML
instead of appendChild/removeChild.</p>
<div id="test"></div>
<script>
/* ORIGINAL queuetest2 CODE FROM DOUGLAS CROCKFORD IS HERE
http://www.crockford.com/javascript/memory/queuetest2.html */
(function (limit, delay)
{
var n = 0;
var add = true;
function makeSpan(n)
{
var div = document.getElementById('test');
//adding also an inline event to stress more the browser
div.innerHTML = "<span onmouseover=\"this.style.color = '#00ff00';\">" + n + "</span>";
var s = div.getElementsByTagName('span')[0];
s.onclick = function(e)
{
s.style.backgroundColor = 'red';
alert(n);
};
return s;
}
function process(n)
{
if(add)
s = makeSpan(n);
else
s.parentNode.innerHTML = ""; //removing span by clearing the div innerHTML
add = !add;
}
function loop()
{
if (n < limit)
{
process(n);
n += 1;
setTimeout(loop, delay);
}
}
loop();
})(10000, 10);
</script>
</body>
答案 2 :(得分:2)
关于Internet Explorer 8 - 他们说他们已经在MS IE8中修复了它:http://msdn.microsoft.com/en-us/library/dd361842(VS.85).aspx
StackOverflow上的类似帖子:Do you know what may cause memory leaks in JavaScript?