3

我有一个问题,想知道如果你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.end后也调用了该对象container.timer。我知道delete只会删除引用,并且一旦删除了对象的所有引用,它就会从内存中删除,但这是否意味着setTimeout还存储对其回调的引用?

本质上,我的问题是:

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

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

4

1 回答 1

4

这是否意味着 setTimeout 还存储了对其回调的引用?

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

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

container.timer 真的被删除了吗?

container从不再具有timer属性的意义上说,是的,但是该timer函数仍然存在,因为setTimeout仍然持有对它的引用。

为什么 setTimeout 回调 container.timer.end 仍然运行?

因为它也被排队了setTimeout。立即运行,start确实

setTimeout(this.end, 2000);

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

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

于 2020-03-31T11:41:06.297 回答