我试图找出Chrome的JavaScript垃圾收集器是否能够收集从DOM中删除的元素的事件监听器,即使未调用removeEventListener。 为此,我正在使用Google Chrome的DevTools(效果标签)检查图表上的“监听器”曲线。
我开发了一个简单的代码,当单击一个按钮时会创建N个div,然后向其中每个添加一个事件侦听器。 然后,当我单击一个div时,所有这些div都会从DOM中删除,并且:
-方案1:不要调用removeEventListener来确定垃圾收集器是否可以自己删除它们(因为元素不再位于DOM中)。
-方案2:调用removeEventListener显式删除其侦听器。 通过比较这两种情况,我认为如果结果相同,那么垃圾收集器实际上将在两种情况下都删除侦听器。
在“性能”选项卡中,以下两种情况均已执行: 1)点击录音按钮 2)强制垃圾收集 3)点击按钮创建div 4)单击div将其从DOM中删除(在第二种情况下,删除其侦听器) 5)强制垃圾收集 6)停止录制。
我得到的结果提出了更多问题。
-方案1:从1个侦听器(按钮的按钮)开始,然后添加N个侦听器(每个div 1个)。在最后一次垃圾回收之后,剩下了2个事件侦听器,一个是按钮的侦听器,另一个是未知的。
问题1::由于垃圾收集器能够删除N个侦听器(或可能是N-1个),所以这个未知事件侦听器是什么?它来自何处?
-场景2:就像场景1一样,从1开始,然后添加N个侦听器,但是奇怪的是,在调用removeEventListener时,添加了N个其他侦听器,所以我们现在有1 + 50 + 50 = 101个侦听器。但是与第一种情况不同,在最后一次垃圾回收之后,仅剩下一个侦听器(按钮的)。
问题2:为什么在调用removeEventListener时添加事件侦听器,这会对性能产生影响吗?
var n = 50;
var divs = [];
btn = document.createElement("button")
btn.style.height = "50px";
document.body.appendChild(btn);
btn.addEventListener("click",f);
function f(){
for(var i=0; i<n; i++){
divs[i] = document.createElement("div")
document.body.appendChild(divs[i]);
divs[i].addEventListener("click",g);
divs[i].style.height = "5px";
divs[i].style.backgroundColor = "blue";
}
console.log("created " + n + " divs with event listeners")
};
function g(){
for(var i=0; i<n; i++){
divs[i].removeEventListener("click",g); //called only in scenario 2
divs[i].parentElement.removeChild(divs[i]);
}
console.log("remove " + n + " divs and their event listeners")
divs = null;
}