为啥元素从 DOM 中移除后仍可访问?
Posted
技术标签:
【中文标题】为啥元素从 DOM 中移除后仍可访问?【英文标题】:Why is an element accessible even after being removed from DOM?为什么元素从 DOM 中移除后仍可访问? 【发布时间】:2015-12-13 08:59:19 【问题描述】:window.a =
div1: $('#div1'),
img1: $('#img1')
;
$(a.img1).click(function()
a.div1.html('<img id="img2" src="https://www.gstatic.com/webp/gallery/2.sm.jpg" />');
$('#img2').click(function()
$(a.img1).attr('src', 'https://www.gstatic.com/webp/gallery/3.sm.jpg');
);
);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="div1">
<img id="img1" src="https://www.gstatic.com/webp/gallery/1.sm.jpg" />
</div>
当第 9 行执行时,即第二次单击图像时$(a.img1).attr('src', 'https://www.gstatic.com/webp/gallery/3.sm.jpg');
,a.img1 不应该存在。那么,为什么该 URL 的 HTTP 请求被发送到服务器(网络选项卡中的通知)?我正在使用 Chrome 版本 45.0.2454.85 m。不要认为这是一个浏览器错误。也适用于 Firefox 39。
还做了一个提琴手http://jsfiddle.net/ismusidhu/vvmwntcd/。
【问题讨论】:
您已经从 DOM 树中删除了该节点,但它仍然存在,因为window.img1
仍然指向它 - 所以它不能被垃圾回收。
“为什么元素从 DOM 中移除后仍然可以访问?” 从DOM
中移除的元素在哪里?
@guest271314 a.div1.html()
应该删除它。不是吗?
@IsmailS 是的,你是对的;从DOM
中删除,但仍然是window.a.img1
处的jQuery 对象
如果你从酒店房间偷了遥控器,当你按下按钮时它仍然会闪烁灯,即使它不会对任何其他电视做任何事情......
【参考方案1】:
作为Marc B said,您已经从DOM 树中删除了该节点,但它仍然存在,因为window.img1
仍然指向它(间接地,通过指向一个反过来指向它的jQuery 对象)——所以它不能被垃圾回收。如果将window.img1
设置为不同的值(例如null
或undefined
),则可以对元素进行垃圾回收。
这样想:你从指向它的图像的父元素(以及各种兄弟元素,但暂时忽略它)开始:
+------------------+ +------------------+ | (一些 DOM 元素)|---------->| | +---------------------+ | | |图像元素| +--------+ | | | img1 |------------>| | +------+ +------------------+然后,当您在其祖先上调用 html
时,DOM 会删除对该元素的所有引用,并且您会得到:
释放最后一个引用,元素可以被回收/释放。
【讨论】:
这是一个真实的答案,那你为什么把它作为社区维基? @IsmailS:CW 是真正的答案。当我看到有人评论了(一个不完整的版本)如果答案很短,我会回答什么时,我经常勾选 CW 框。我不关心代表,这似乎有助于避免抱怨从 cmets 那里“偷走”他们的“答案”。 (我不认为 Marc B 会那样抱怨,但我是从别人那里得到的,所以......) 那是您的伟大,先生!无论如何,如果有人抱怨窃取答案,那一定是他们的错。你已经详细说明了。他们没有。 ;)【参考方案2】:window.a =
div1: $('#div1'),
img1: function()
return $("> img[id]", this.div1)
;
function toggle(e)
a.div1.html(/1/.test(e.target.src)
? '<img id="img2" src="https://www.gstatic.com/webp/gallery/2.sm.jpg" />'
: $('<img id="img1" src="https://www.gstatic.com/webp/gallery/1.sm.jpg" />')
.click(toggle)
);
$("#img2").on("click", function(e)
a.img1().attr(
'src': 'https://www.gstatic.com/webp/gallery/3.sm.jpg',
"id": "img3"
)
.click(toggle)
);
a.img1().click(toggle);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="div1">
<img id="img1" src="https://www.gstatic.com/webp/gallery/1.sm.jpg" />
</div>
jsfiddle http://jsfiddle.net/vvmwntcd/6/
【讨论】:
浏览器仍然向https://www.gstatic.com/webp/gallery/3.sm.jpg
发出请求。在网络选项卡上检查。控制台确实显示undefined
。
@IsmailS:控制台显示undefined
的唯一原因是代码输出a.img
而不是a.img1
。这样做is
检查 before 元素被删除并不会让它在以后神奇地消失。如果你使用corrected version,你会看到a.img1
仍然是一个jQuery对象(当然),a.img1[0]
仍然有一个HTMLInputElement
对象的引用(当然)。
@IsmailS:你的问题的答案是 Marc B 早先所说的:它仍然存在,因为仍然有对它的引用。在显示图像之前使用断开连接的img
获取图像是一种常用技术。为避免这种情况发生,请清除 img1
。以上是关于为啥元素从 DOM 中移除后仍可访问?的主要内容,如果未能解决你的问题,请参考以下文章