函数内创建的JavaScript对象生命周期:点击删除为何仍生效?
问题:动态创建列表项后,内部
MyObj实例为何未被销毁? 我有一个HTML列表<ul>,通过JavaScript动态添加<li>项,最终结构如下:
<ul id="parent"> <li> <!-- container --> Some text <button>Delete</button> </li> </ul>
其中<button>用于删除对应的<li>,我创建了包含delete方法的MyObj类:
class MyObj { constructor(parent, container) { this.parent = parent; this.container = container; } delete() { this.parent.removeChild(this.container); } }
创建<li>元素的函数代码如下:
function create() { let container = document.createElement('li'); let deleteContainerBtn = document.createElement('button'); container.innerHTML = "Sometext"; container.appendChild(deleteContainerBtn); parent.appendChild(container); const obj = new MyObj(parent, container, deleteContainerBtn); deleteContainerBtn.onclick = function() { obj.delete() }; };
当前功能正常:调用create函数可添加多个<li>,点击Delete按钮可删除对应<li>。但我有疑问:create函数执行完毕后,内部创建的obj对象为何未被销毁,仍能执行delete方法?
解答
这是因为闭包保留了对obj的引用,再结合JavaScript基于引用计数的垃圾回收机制,只要对象还有未被释放的引用,就不会被销毁。具体逻辑如下:
- 在
create函数内,你给deleteContainerBtn的onclick绑定了一个匿名函数,这个函数内部直接引用了obj。 - 这个匿名函数作为按钮的事件处理函数,会被浏览器的事件系统保留引用(只要按钮元素还存在于DOM中)。
- 由此形成了完整的引用链:DOM中的按钮 → 点击事件函数 →
obj,所以垃圾回收器不会回收obj。 - 直到你点击按钮执行
delete方法,把<li>(即container)从DOM中移除,按钮元素随之被销毁,事件处理函数的引用也会被释放,这时obj才会失去所有有效引用,最终被垃圾回收器销毁。
内容的提问来源于stack exchange,提问作者Derek Topovski
相关产品推荐
相关产品推荐

