慕仙森
2023-07-06 18:27:43
考慮我們有一些系統(tǒng)的模塊 (M) 和事件發(fā)射器 (E),它們提供 M 所需的一些更新。當(dāng) M 訂閱 E 時(shí),它將回調(diào)函數(shù) (F) 傳遞給 E。此時(shí) E 將引用 F,而 F 將引用參考 M (E → F → M)。這意味著由于事件發(fā)射器,M 無(wú)法被垃圾收集。但從概念上講,當(dāng) M 不再被系統(tǒng)引用時(shí),它不需要 E 進(jìn)行任何更新,因此 E 不應(yīng)該阻止它被垃圾收集。在當(dāng)今的 JavaScript 訂閱模型中,它是通過(guò)返回顯式處置器 (DF) 來(lái)解決的,DF 是一個(gè)取消特定訂閱的函數(shù)。但我認(rèn)為這很糟糕,原因有兩個(gè)。首先,它打破了 JavaScript 的自然規(guī)則:當(dāng)某些東西無(wú)法通過(guò)引用訪問(wèn)時(shí),該東西就會(huì)被垃圾收集。其次,處理器是一個(gè)額外的參考。所以,現(xiàn)在 DF 引用了 E,因此不僅 E 阻止 M 進(jìn)行 gc,反之亦然(M → DF → E 和 E → F → M)??磥?lái)這是一個(gè)使用弱引用的好地方。但是,我無(wú)法弄清楚如何在 WeakMap 或 WeakSet 之上構(gòu)建事件發(fā)射器。即使你把訂閱放在弱容器中,當(dāng)你需要發(fā)出時(shí),你仍然需要一些硬引用來(lái)取出它們。這完全抵消了弱容器的好處!我最好的想法是一個(gè)假設(shè)的“支持迭代的WeakSet”。除了通常的 API: 之外add,此類對(duì)象has還delete應(yīng)該具有forEachWeak,它與通常的 forEach 一樣工作,并授予對(duì)迭代對(duì)象的臨時(shí)所有權(quán)。如果用戶不將此類對(duì)象提取到其他硬引用容器(如數(shù)組)中,這不會(huì)打破引用的弱點(diǎn),并且仍然允許迭代。在事件發(fā)射器的情況下,此類發(fā)射器將能夠發(fā)出對(duì)訂閱的更新,而無(wú)需永久引用它們。那么,是否可以以這種方式或任何其他方式構(gòu)建非擁有事件發(fā)射器?
1 回答

人到中年有點(diǎn)甜
TA貢獻(xiàn)1895條經(jīng)驗(yàn) 獲得超7個(gè)贊
但從概念上講,當(dāng) M 不再被整個(gè)系統(tǒng)引用時(shí),它不需要 E 進(jìn)行任何更新
那要看。這只有在 M 完全被動(dòng)的情況下才有效。一旦您想使用 M 實(shí)際執(zhí)行某些操作,您就需要它來(lái)獲取更新,無(wú)論其他內(nèi)容是否引用它。通過(guò)將 M 存儲(chǔ)在全局變量(?)中來(lái)保持訂閱活動(dòng)并通過(guò)嘗試對(duì)其進(jìn)行垃圾收集(這不是確定性的)來(lái)取消訂閱是相當(dāng)困難的。另一方面,顯式處置器則清晰且簡(jiǎn)單。
我無(wú)法弄清楚如何在 WeakMap 或 WeakSet 之上構(gòu)建事件發(fā)射器。
這不可能。WeakMap/WeakSet實(shí)際上是ephemerons,它們不提供弱引用。
添加回答
舉報(bào)
0/150
提交
取消