从我回忆的不远的过去来看,Javascript 解释器在面对循环引用时会遇到内存泄漏问题。
在最新的浏览器中仍然如此吗?(例如 Chrome、FF 3.5 等)
从我回忆的不远的过去来看,Javascript 解释器在面对循环引用时会遇到内存泄漏问题。
在最新的浏览器中仍然如此吗?(例如 Chrome、FF 3.5 等)
当您在 JavaScript 对象和宿主对象(如 DOM 节点)之间创建引用循环时,我们讨论的与 JavaScript 相关的绝大多数泄漏都具体发生在 IE6-7 中。
在 IE6 中,这是特别有害的,因为当您离开页面时,您无法取回内存。它消失了,直到您退出浏览器。在 IE7 中,清除页面现在确实会返回内存,但是当您有一个长时间运行的应用程序时,您仍然会遇到困难。IE8 通过将 DOM 节点转换为原生 JavaScript 对象而不是宿主对象,很好地解决了大部分问题。(您仍然可以通过在引用循环中包含其他非本地对象(如 ActiveX 对象)来触发 IE8 中的泄漏。)
对于所有浏览器,尤其是在旧版本中,随机位置肯定仍然会潜伏着一些不明显的内存泄漏。但是没有一种方法可以像 IE 重新循环问题那样轻松分类和避免它们。
为了增加bobince答案,我用IE8做了一些测试。
我尝试了http://www.javascriptkit.com/javatutors/closuresleak/index.shtml提供的几乎所有示例
除了删除仍然附加事件的子节点的示例之外,它们中的任何一个都不再泄漏内存(至少不是以可感知的方式)。
这种类型的例子我认为Douglas Crockford在他的 queuetest2 中解释得更好。
这仍然会在 IE8 上泄漏内存,只需运行测试脚本并查看 Windows 任务管理器 - 性能 - PF 使用情况,就可以很容易地进行测试。您会看到每个循环的 PF 使用率增加了近 1MB(非常快)。
但在 IE8 中,内存在页面卸载时释放(例如导航到新页面或重新加载同一页面),显然在完全关闭浏览器时也是如此。
因此,为了让最终用户在 IE8 上感知到这种内存泄漏(作为降低的系统性能),他需要长时间停留在同一页面上,这在现在 AJAX 经常发生,但是这个页面也需要执行数百个子节点删除带有事件的元素。
Douglas Crockford 测试强调浏览器添加了 10000 个节点然后删除,这非常适合向您展示问题,但在现实生活中,我从未有过删除超过 10 个元素的页面。INMHO 通常使用起来display: none
比删除一整套节点更快,这就是我不使用removeChild
那么多的原因。
对于可能对上面解释的 IE8 内存泄漏更感兴趣的人,我做了另一项测试,似乎在使用 IE8代替添加/删除带有附加事件的子元素时,内存泄漏根本不会出现。innerHTML
appendChild/removeChild
显然,Douglas Crockford清除功能(由他建议以防止 IE 中的内存泄漏)在 IE8 中不再需要,至少在使用innerHTML
...
(编辑感谢下面的 4esn0k 评论)...此外,Douglas Crockford purge 函数在 IE8 上根本不起作用,在他的代码中,var a = d.attributes
没有返回在 IE8 上运行时添加的onclick
属性(或任何其他onevent
属性)(它们确实在 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>
关于 Internet Explorer 8 - 他们说他们已经在 MS IE8 中修复了它:http: //msdn.microsoft.com/en-us/library/dd361842 (VS.85).aspx
StackOverflow 上有一个类似的帖子:你知道什么可能导致 JavaScript 中的内存泄漏吗?