为什么删除对象后setTimeout仍然调用回调

How come setTimeout still calls callback after object deletion

我有一个问题,想知道如果你从对象调用 setTimeout,然后 deleted 对象,setTimeout 回调是否仍然被调用?

显然是的。

var container = {
    timer: { // the object to be deleted
        start: function() {
            console.log('start');
            setTimeout(this.end, 2000);
        },
        end: function() {
            console.log('end');
        },
    },

    timerStart: function() { 
        this.timer.start();
        setTimeout(this.timerDelete, 1000);
    },

    timerDelete: function() {
        console.log(delete this.timer);
        console.log('deleted timer');
    },
};

致电 container.timerStart(); 后,我收到以下信息:

> container.timerStart();
  start
< undefined
  true
  deleted timer
  end

因此显示对象container.timer删除成功,而且在container.timer删除后也调用了container.timer.end。我知道 delete 只删除引用,一旦对象的所有引用都被删除,它就会从内存中删除,但这是否意味着 setTimeout 也存储对其回调的引用?

本质上,我的问题是:

  1. container.timer真的被删除了吗?
  2. 为什么 setTimeout 回调 container.timer.end 仍然 运行?
  3. setTimeout 实际如何参考这种行为?

非常感谢任何反馈或阅读资源。谢谢!

does this mean that setTimeout also stores a reference to its callback?

是的,这正是正在发生的事情。它有点类似于:

const obj = {
  fn: () => console.log('fn')
};
const fn = obj.fn;
delete obj.fn;
fn();

Is container.timer actually deleted?

从某种意义上说 container 不再有 timer 属性,是的,但是 timer 函数仍然存在,因为 setTimeout 仍然成立对其的引用。

Why does the setTimeout callback container.timer.end still run?

因为它也在 setTimeout 中排队。 start 立即运行,

setTimeout(this.end, 2000);

所以 setTimeout 保存对函数的引用 this.end 并在几秒钟后调用它。

只有当 nothing 不再持有对它的引用(可能是循环引用除外)时,才会进行垃圾回收。如果某些东西存储在闭包或回调中,并且仍然可以引用回调,则不会对其进行 GC,至少在没有任何东西可以再引用它之前不会。