在typeScript中是否有析构函数

Gáb*_*pák 48 javascript destructor typescript

TypeScript中有析构函数吗?如果没有,我该如何删除对象?我尝试过destructor(),~ClassName()但它没有用.

Rya*_*ugh 51

JavaScript使用垃圾收集在不再引用对象时自动删除对象.没有析构函数或终结符的概念.

您无法观察垃圾收集器何时删除对象,也无法预测.

  • 这不是一个正确的答案.GáborLupák最喜欢知道那里发生了垃圾收集.即使使用垃圾收集器,您仍然需要在应用程序执行期间在特定点释放一些长生存引用,以便引用资源可以符合垃圾收集条件,或者至少不会发生内存泄漏.我的建议是你创建一个接口(例如:interface Releasable {}并定义一个名为release()的方法,也许是一个名为release的标志,你可以使用它来阻止不止一次运行release(). (16认同)
  • 如果计时器,回调或事件侦听器仍然附加到要删除的对象的某处,则可以防止垃圾收集.如果回调/侦听器仍然存在但对象不存在,您也可能会收到错误.如果你想绝对确定你可以编写自己的析构函数方法并在删除对象之前调用它. (6认同)
  • @asiby - 这将是一个合适的*解决方法*,但该解决方案**不是析构函数**.这个答案是正确的 - Javascript没有析构函数. (5认同)
  • 最后,析构函数不需要与 GC 建立任何关系即可工作。严格来说,析构函数是在对象的生命周期结束时调用的,而不是在对象被收集时调用(无论如何,必须在调用析构函数之后)。因此,我们不需要将析构函数调用与 GC 的操作同步。实际上,析构函数可以在收集之前的任何点被触发。如果语言的语义支持静态生命周期,则编译器可以在对象生命周期到期之前(例如,当它离开程序范围时)合成“obj.destruct()”。 (4认同)

FZs*_*FZs 15

从 ES2021 开始,终结器已添加到规范中。

要使用该功能,您需要创建一个FinalizationRegistry,它会在任何关联对象被垃圾收集时通知您。

你可以这样使用它:

const reg = new FinalizationRegistry((id: number) => {
  console.log(`Test #${id} has been garbage collected`);
});

class Test{
  id: number;
  constructor(id: number){
    this.id = id;
    reg.register(this, this.id);
    //                 ^^^^^^^--- This is the "testament", whatever value, which will be passed to the finalization callback
  }
}

{
  const test1 = new Test(1);
  const test2 = new Test(2);
}
Run Code Online (Sandbox Code Playgroud)

请注意,当回调被调用时,该对象已经被垃圾回收了;只有它的“遗嘱”(或者正如 MDN 所说,不太戏剧化的是“持有值”)被赋予终结器。

如果您需要访问终结器中对象的某些属性,则可以将它们存储在遗嘱中,在这种情况下,可以(尽管不一定会)在原始对象之后被垃圾收集:

interface TestTestament{
  id: number,
  intervalid: ReturnType<typeof setInterval>
}

const reg = new FinalizationRegistry((testament: TestTestament) => {
  console.log(`Test #${testament.id} has been garbage collected`);
  clearInterval(testament.intervalid);
});

class Test{
  private testament: TestTestament;
  constructor(id: number){
    this.testament = {
      id,
      intervalid: setInterval(() => {
        console.log(`Test interval #${id}`);
      }, 1000)
    };

    reg.register(this, this.testament);
  }
}

{
  const test1 = new Test(1);
  const test2 = new Test(2);
}
Run Code Online (Sandbox Code Playgroud)

请注意,规范不保证垃圾收集何时发生,因此如果对象保留在内存中,则终结器甚至可能不会被调用。