jld*_*ont 24 javascript browser memory-leaks circular-reference
从我记得的一个不太遥远的过去,Javascript解释器在面对循环引用时遭遇了内存泄漏问题.
在最新的浏览器中仍然如此吗?(例如Chrome,FF 3.5等)
bob*_*nce 28
当您在JavaScript对象和DOM节点之类的宿主对象之间建立引用循环时,我们与JavaScript讨论的绝大多数泄漏都特别在IE6-7中.
在IE6中,这是特别有害的,因为当你离开页面时你没有得到回忆; 它一直消失,直到你退出浏览器.在IE7中清除页面现在会返回内存,但是当你有一个长时间运行的应用程序时仍然会遇到困难.IE8通过将DOM节点转换为本机JavaScript对象而不是主机对象来正确解决大部分问题.(您仍然可以通过在参考循环中包含其他非本机对象(如ActiveX对象)来触发IE8中的泄漏.)
对于所有浏览器,随机位置肯定会出现小的模糊内存泄漏,特别是在旧版本中.但是没有一种方法可以像IE refloop问题那样轻松地分类和避免它们.
Mar*_*aio 17
为了增加bobince的答案,我用IE8做了一些测试.
我尝试了http://www.javascriptkit.com/javatutors/closuresleak/index.shtml提供的几乎所有示例
他们中的任何一个都不再泄漏内存(至少不是以可感知的方式),除了删除仍然附加有事件的子节点的示例.
这种类型的例子我认为道格拉斯克罗克福德在他的队列测试2中更好地解释了这个例子.
这个仍然在IE8上泄漏内存,只需运行测试脚本并查看Windows任务管理器 - 性能 - PF使用情况就可以轻松测试.您将看到每次循环PF使用量增加近1MB(非常快).
但是在IE8中,内存在页面卸载时释放(比如导航到新页面或重新加载同一页面),显然也是在完全关闭浏览器时.
因此,为了让最终用户能够感知IE8上的内存泄漏(因为系统性能降低),他需要长时间保持在同一页面上,这在现在可能经常发生在AJAX中,但此页面还需要做几百个子节点删除附加事件的元素.
道格拉斯克罗克福德测试强调浏览器添加了10000个节点然后删除,这非常适合向您展示问题,但在现实生活中,我从未有过删除超过10个元素的页面.INMHO通常使用速度更快,display: none而不是删除整个节点集,这就是为什么我不使用removeChild那么多.
对于那些可能对上面解释的IE8内存泄漏更感兴趣的人,我做了另一个测试,当使用innerHTML代替appendChild/removeChild添加/删除附加事件的子元素时,IE8中似乎没有显示内存泄漏.所以显然道格拉斯·克罗克福德的清除功能(由他建议防止IE中的内存泄漏)在IE8中不再需要了,至少在使用时innerHTML......
(感谢下面的4esn0k评论)...而且Douglas Crockford 清除函数在IE8上根本不起作用,在他的代码中var a = d.attributes返回在IE8上运行时添加的NO 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>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8883 次 |
| 最近记录: |