为了账号安全,请及时绑定邮箱和手机立即绑定

是否可以在 JavaScript 中创建不拥有订阅的事件发射器?

是否可以在 JavaScript 中创建不拥有订阅的事件发射器?

慕仙森 2023-07-06 18:27:43
考虑我们有一些系统的模块 (M) 和事件发射器 (E),它们提供 M 所需的一些更新。当 M 订阅 E 时,它将回调函数 (F) 传递给 E。此时 E 将引用 F,而 F 将引用参考 M (E → F → M)。这意味着由于事件发射器,M 无法被垃圾收集。但从概念上讲,当 M 不再被系统引用时,它不需要 E 进行任何更新,因此 E 不应该阻止它被垃圾收集。在当今的 JavaScript 订阅模型中,它是通过返回显式处置器 (DF) 来解决的,DF 是一个取消特定订阅的函数。但我认为这很糟糕,原因有两个。首先,它打破了 JavaScript 的自然规则:当某些东西无法通过引用访问时,该东西就会被垃圾收集。其次,处理器是一个额外的参考。所以,现在 DF 引用了 E,因此不仅 E 阻止 M 进行 gc,反之亦然(M → DF → E 和 E → F → M)。看来这是一个使用弱引用的好地方。但是,我无法弄清楚如何在 WeakMap 或 WeakSet 之上构建事件发射器。即使你把订阅放在弱容器中,当你需要发出时,你仍然需要一些硬引用来取出它们。这完全抵消了弱容器的好处!我最好的想法是一个假设的“支持迭代的WeakSet”。除了通常的 API: 之外add,此类对象has还delete应该具有forEachWeak,它与通常的 forEach 一样工作,并授予对迭代对象的临时所有权。如果用户不将此类对象提取到其他硬引用容器(如数组)中,这不会打破引用的弱点,并且仍然允许迭代。在事件发射器的情况下,此类发射器将能够发出对订阅的更新,而无需永久引用它们。那么,是否可以以这种方式或任何其他方式构建非拥有事件发射器?
查看完整描述

1 回答

?
人到中年有点甜

TA贡献1895条经验 获得超7个赞

但从概念上讲,当 M 不再被整个系统引用时,它不需要 E 进行任何更新

那要看。这只有在 M 完全被动的情况下才有效。一旦您想使用 M 实际执行某些操作,您就需要它来获取更新,无论其他内容是否引用它。通过将 M 存储在全局变量(?)中来保持订阅活动并通过尝试对其进行垃圾收集(这不是确定性的)来取消订阅是相当困难的。另一方面,显式处置器则清晰且简单。

我无法弄清楚如何在 WeakMap 或 WeakSet 之上构建事件发射器。

这不可能。WeakMap/WeakSet实际上是ephemerons,它们不提供弱引用。


查看完整回答
反对 回复 2023-07-06
  • 1 回答
  • 0 关注
  • 104 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信