如何在DOM中删除图像时防止内存泄漏?
webkit中有一个已知的bug ,当你从DOM中移除一个图像时,它不会释放与之关联的内存。
这是经常加载图像的单页应用程序的问题。
各种build议解决scheme是:
- 从DOM中删除图像之前删除图像的src属性
- 将图像src设置为“”,然后从DOM中删除图像
- 将图像从DOM中移除之前,将图像设置为单个像素图像
- 创build有限数量的图像元素并继续回收
前3种方法不适合我。 回收图像元素的主要缺点是,这意味着要编写大量的代码来pipe理它。 我通过可能包含图像的AJAX加载新的HTML,所以我不一定知道将被加载的图像的数量。
有没有其他的解决办法来解决这个问题?
我使用了3种不同的方法
首先 。 添加了一组图像,并将垃圾收集留给浏览器。
这绝对是垃圾收集,但过了一段时间,确保没有需要创build的图像。
第二 。 使用数据:URI模式为图像的src。
var s = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="; for (var i = 0; i < 100; i++){ var img = document.createElement("img"); img.src = s; document.getElementById("myList1").appendChild(img); setTimeout(function(){img = null;}, 1000); }
这看起来很相似,虽然我在浏览器前看到的好一点,但是观察到使用较less的内存,垃圾收集几乎和上面一样。
第三 。 垃圾收集代码中。
var s = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="; for (var i = 0; i < 100; i++){ var img = document.createElement("img"); img.src = "dot.png"; // or the other, both mean the same here. img.src = s; document.getElementById("myList1").appendChild(img); setTimeout(function(){img = null;}, 1000); }
在这短暂的testing中,我相信最后一种方法效果更好,因为它几乎可以立即释放空间,而不用等待进一步的参考图像。
总而言之,当你绝对觉得某些东西必须被释放时,你最好自己动手垃圾回收。
一个基本的图像池应该允许你回收利用img元素来重新使用。 既然你不知道有多less图像会提前总计,只是有必要扩大池大小。
像这样的东西应该工作:
function getImg( id, src, alt ) { var pool = document.getElementById( 'image_pool' ); var img = ( pool.children.length > 0 ) ? pool.removeChild( pool.children[0] ) : document.createElement( 'img' ); img.id = id; img.src = src; img.alt = alt; return img; } function recycleImg( id ) { var img = document.getElementById( id ); document.getElementById( 'image_pool' ).appendChild( img.parentNode.removeChild( img ) ); }
在你的页面上放置一个隐藏的“image_pool”容器,以便在使用之间隐藏回收的图像:
<div id="image_pool" style="display:none;"></div>
那么任何时候你需要一个新的img元素,请调用:
document.getElementById( 'some_element_id' ).appendChild( getImg( 'my_image_id', 'images/hello.gif', 'alt_text' ) );
当你完成它时:
recycleImg( 'my_image_id' );
jQuery的替代
function getImg( id, src, alt ) { var img; if( $("#image_pool").children().length > 0 ) { return $("#image_pool img:first-child").attr( { 'id': id, 'src': src, 'alt': alt } ).detach(); } return $( "<img />'" ).attr( { 'id': id, 'src': src, 'alt': alt } ); } function recycleImg( id ) { $( "#" + id ).detach().appendTo( $("#image_pool") ); }
当你需要一个新的img元素时:
getImg( 'my_image_id', 'images/hello.gif', 'alt_text' ).appendTo( $( "#some_element_id" ) );
(回收工作与上述相同)
尝试将Javascript DOM树对象设置为“null”。
首先,使用类似于Chrome开发人员工具界面的东西,将对象定位到DOM树层次结构中,并检查它并find包含图像二进制文件的对象。
尝试将该对象设置为null,如var obj = null;
。
这应该告诉Javascript,孩子不再被引用,并强制对象的内存被释放。
将图像设置为div的背景是什么? 我相信Flickr正在为他们的移动html5应用程序做这样的事情。