含未兑现Promise的Component实例调用deleteComponents后能否被垃圾回收?
未兑现Promise的组件能否被垃圾回收?
假设有如下Component类:
class Component { constructor() { this.resolvers = []; } addResolver() { return new Promise((resolve) => { this.resolvers.push(resolve); }); } callResolvers() { this.resolvers.forEach((resolver) => resolver()); } }
另有以下代码片段:
let components = []; async function addComponent() { const component = new Component(); components.push(component); await component.addResolver(); console.log("resolver called"); } function deleteComponents() { components = []; } function resolveComponents() { components.forEach((component) => component.callResolvers()); } addComponent(); addComponent(); addComponent(); resolveComponents();
调用resolveComponents()时,resolver会被触发。现在的疑问是:如果调用deleteComponents()替代resolveComponents(),即执行如下代码:
addComponent(); addComponent(); addComponent(); deleteComponents();
这些包含未兑现Promise的组件能否被垃圾回收?
这些组件以及关联的未兑现Promise完全可以被垃圾回收,原因如下:
- JS的垃圾回收基于可达性规则:只要对象没有任何从全局上下文或活跃执行变量出发的可达引用链,就会被标记为可回收。
- 执行
deleteComponents()后,components数组被重置为空,原来的Component实例失去了唯一的外部引用——没有任何其他变量或代码能再访问到这些实例。 - 虽然每个
Component实例的resolvers数组里存着Promise的resolve函数,Promise本身也持有这个resolve的引用,但反过来,这些resolve函数和未兑现的Promise都没有被外部代码持有引用,整个关联的对象链都处于不可达状态。 - 垃圾回收器会识别到这一点,将所有相关的
Component实例、resolvers数组、resolve函数以及未兑现的Promise全部清理掉。
内容的提问来源于stack exchange,提问作者Jose Carlos Ramírez
相关产品推荐
相关产品推荐

