Javascript 删除DOM中的图像时如何防止内存泄漏?
有一种情况是,当您从DOM中删除图像时,它不会释放与其关联的内存 这是经常加载图像的单页应用程序的一个问题 各种建议的解决方案包括:Javascript 删除DOM中的图像时如何防止内存泄漏?,javascript,html,webkit,Javascript,Html,Webkit,有一种情况是,当您从DOM中删除图像时,它不会释放与其关联的内存 这是经常加载图像的单页应用程序的一个问题 各种建议的解决方案包括: 在从DOM中删除图像之前,请将图像src设置为“” 在从DOM中删除图像之前,将图像设置为单像素图像 前三种方法不适合我。回收图像元素的主要缺点是,这意味着要编写大量代码来管理图像元素。我正在通过AJAX加载可能包含图像的新HTML,因此我不一定知道将加载的图像数量 是否有其他解决方法来解决此问题?尝试将Javascript DOM树对象设置为“null”
- 在从DOM中删除图像之前,请将图像src设置为“”
- 在从DOM中删除图像之前,将图像设置为单像素图像
是否有其他解决方法来解决此问题?尝试将Javascript DOM树对象设置为“null” 首先,使用类似于chrome开发者工具界面的东西,在DOM树层次结构中找到对象,并检查它,找到包含图像二进制的对象 尝试将该对象设置为null,例如
var obj=null代码>
这将告诉Javascript不再引用子对象,并强制释放对象的内存。将图像作为背景设置为div怎么样?我相信Flickr正在为他们的移动html5应用程序做类似的事情。一个基本的图像池应该允许你回收img元素以供重复使用。因为您不知道提前会有多少个图像,所以只需根据需要扩展池大小即可
像这样的方法应该会奏效:
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 ) );
}
在页面的某个位置放置一个隐藏的“图像池”容器,以便在使用之间隐藏回收的图像:
<div id="image_pool" style="display:none;"></div>
当你完成它时:
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") );
}
(回收工作同上)我使用了3种不同类型的方法
首先。添加了一组图像,并将垃圾收集留在浏览器中。
它肯定是垃圾收集的,但是过了一段时间,确保不需要创建图像
秒。为图像的src使用了data:URI模式
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);
}
var s=“data:image/png;base64,ivborw0kggoaaaansuhueugaaaaaaaafcayaacnblaaaaheleqvqi12p4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=”;
对于(变量i=0;i<100;i++){
var img=document.createElement(“img”);
img.src=s;
document.getElementById(“myList1”).appendChild(img);
setTimeout(函数(){img=null;},1000);
}
这看起来很相似,但对我来说更好一点,因为我在浏览器前观看,发现使用的内存更少,垃圾收集几乎与上面相同
第三。在代码中执行垃圾收集
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);
}
var s=“data:image/png;base64,ivborw0kggoaaaansuhueugaaaaaaaafcayaacnblaaaaheleqvqi12p4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=”;
对于(变量i=0;i<100;i++){
var img=document.createElement(“img”);
img.src=“dot.png”;//或其他,两者在此处的含义相同。
img.src=s;
document.getElementById(“myList1”).appendChild(img);
setTimeout(函数(){img=null;},1000);
}
在这短短的测试时间里,我相信最后一种方法效果更好,因为它几乎可以立即释放空间,而不必等待进一步查看是否需要参考图像
总而言之,当您觉得必须释放某些内容时,最好自己使用垃圾收集。设置为null
至少是解决方案。(Firefox 69)
在一个项目中,我加载了1-5批的图像以进行比较。平均8-9MB的图像。在移除后,如果不将img
元素设置为null
,则RAM的累积非常显著,并耗尽了可用内存
因此,改变了这一点:
function clear (n) {
while (n.lastChild) {
n.removeChild(n.lastChild);
return n;
};
为此:
function clear (n) {
let x;
while (n.lastChild) {
x = n.removeChild(n.lastChild);
x = null;
}
return n;
};
现在根本没有内存积累。我认为映像池不会有那么多代码;而且它可以很容易地支持任意数量或图像。删除src
属性有什么问题?取决于什么(和如果)您正在使用的库在删除img之前,您可以先通过删除src
包装节点删除函数来处理这种特殊情况。刚刚更新了我的问题-删除src属性对我不起作用。如果手动调用每个图像的Image()构造函数,您怎么可能不知道图像的数量(链接错误的原因)。我不认为这个错误涵盖了使用img标记注入html的问题。你说的“Javscript对象本身不被垃圾收集”到底是什么意思?需要更多的解释,或者-一般来说-是错误的。对不起,是的,它们是垃圾收集的,但并不总是立即收集的-您是否尝试按照我的建议设置为“null”?是否有用?使用chrome在DOM树中定位对象是否也有帮助?我不确定,但在JQuery中分离实际上会破坏节点,appendTo会创建一个新的否DOM中的de。因此实际上根本没有回收。有趣的是,我必须查看源代码以进行验证。无论哪种方式,我都会在这里添加一个不使用jQuery函数的版本,仅供参考。在这里发布了一个问题:@GuillermoGutiérrez听起来像是在detach()和remove()中都保留了元素函数,所以在我上面的代码中,元素应该按照预期正确循环使用。使用数据:URI
你错过了所有浏览器HTTP缓存…在生产应用程序中,这将非常明显。有效点。我通常将所有元素都放在css
或js
中并缓存这些资产。是的,但在这个应用程序中,图像是内容,所以它不会起作用。怎么会不起作用?我不想反对你,但这种方法怎么会不起作用呢
function clear (n) {
while (n.lastChild) {
n.removeChild(n.lastChild);
return n;
};
function clear (n) {
let x;
while (n.lastChild) {
x = n.removeChild(n.lastChild);
x = null;
}
return n;
};