ECMAScript 6 类析构函数

2022-08-30 04:45:48

我知道 ECMAScript 6 有构造函数,但是 ECMAScript 6 有析构函数这样的东西吗?

例如,如果我在构造函数中将对象的某些方法注册为事件侦听器,则我希望在删除对象时将其删除。

一种解决方案是制定一个约定,即为每个需要这种行为的类创建一个方法,并手动调用它。这将删除对事件处理程序的引用,因此我的对象将真正准备好进行垃圾回收。否则,由于这些方法,它将保留在内存中。destructor

但是我希望 ECMAScript 6 有一些原生的东西,这些东西会在对象被垃圾回收之前被调用。

如果没有这样的机制,那么针对此类问题的模式/惯例是什么?


答案 1

ECMAScript 6 是否有像析构函数这样的东西?

不。EcmaScript 6 根本没有指定任何垃圾回收语义[1],所以也没有什么比“破坏”更好的了。

如果我在构造函数中将对象的某些方法注册为事件侦听器,我希望在删除对象时删除它们

一个破坏者甚至不会在这里帮助你。事件侦听器本身仍然引用您的对象,因此在取消注册之前,它将无法进行垃圾回收。
您实际要查找的是一种注册侦听器而不将其标记为实时根对象的方法。(请向您当地的事件源制造商咨询此类功能)。

1):嗯,从 WeakMapWeakSet 对象的规范开始。然而,真正的弱引用仍在管道中[1][2]


答案 2

我只是在搜索有关析构函数时遇到了这个问题,我认为您的评论中有一个未解答的问题,所以我想我会解决这个问题。

谢谢你们。但是,如果 ECMAScript 没有析构函数,那么什么是好的约定呢?我是否应该创建一个名为析构函数的方法,并在完成对象后手动调用它?还有其他想法吗?

如果你想告诉你的对象,你现在已经完成了它,并且它应该专门释放它拥有的任何事件侦听器,那么你可以创建一个普通的方法来做到这一点。你可以调用该方法,如 or or 或类似的任何内容。这个想法是,你告诉对象将自己与它所挂接的任何其他东西断开连接(取消注册事件侦听器,清除外部对象引用等)。您必须在适当的时间手动调用它。release()deregister()unhook()

如果同时还确保没有对该对象的其他引用,则此时您的对象将有资格进行垃圾回收。

ES6确实有weakMap和weakSet,它们是跟踪一组仍然处于活动状态的对象而不影响它们何时可以被垃圾回收的方法,但是当它们被垃圾回收时,它不会提供任何类型的通知。它们只是在某个时候从弱映射或弱集消失(当它们被GCed时)。


仅供参考,您请求的这种类型的析构函数(可能也是为什么没有太多调用它的原因)是,由于垃圾回收,当一个项目具有针对活动对象的开放事件处理程序时,它不符合垃圾回收的条件,因此即使存在这样的析构函数,在您实际删除事件侦听器之前,它永远不会在您的环境中被调用。而且,一旦删除了事件侦听器,就不需要析构函数来实现此目的。

我想有一种可能性不会阻止垃圾回收,但这样的事情也不存在。weakListener()


仅供参考,这是另一个相关问题,为什么垃圾回收语言中的对象析构函数范式普遍不存在?本讨论涵盖终结器、析构函数和处理器设计模式。我发现看到这三者之间的区别很有用。


2020年编辑 - 对象终结器提案

有一个阶段 3 EMCAScript 建议在对对象进行垃圾回收后添加用户定义的终结器函数。

从此类功能中受益的规范示例是包含打开文件的句柄的对象。如果对象被垃圾回收(因为没有其他代码仍然有对它的引用),那么这个终结器方案允许人们至少向控制台发送一条消息,指出外部资源刚刚泄漏,并且应该修复其他地方的代码以防止这种泄漏。

如果你仔细阅读这个提案,你会发现它不像一个像C++这样的语言中成熟的析构函数。此终结器是在对象已被销毁后调用的,您必须预先确定需要将实例数据的哪一部分传递给终结器才能完成其工作。此外,此功能不是用于正常操作,而是作为调试辅助工具以及针对某些类型的 Bug 的后盾。您可以在提案中阅读有关这些限制的完整说明。