网站搜索

如何打破 TypeScript 中的强引用循环?


在我的实现中,我有一个类似树的结构,包含父对象和子对象。父对象有一个子列表,子对象有一个指向父对象的引用,以便能够轻松地在树中导航。现在我想知道,由于我们这里存在强引用循环(我不清楚 TypeScript 中的弱指针),这样的结构是否会被垃圾回收。

这里有一个(非常简单)的例子来说明这种结构,尽管我相信每个人都能想象出它会是什么样子:

class Symbol {
    protected parent: Symbol | undefined;
    protected children: Symbol[];
}

对于这种数据结构,推荐的方法是什么?使用(相对)较新的 WeakMap 或 WeakSet 类来引用父对象(听起来很丑陋)吗?

答案#1

表示树的方法有很多,哪一种最好取决于你如何使用你的树结构。
如果你对现在的情况感到满意,并且只关心垃圾回收,那么为什么不为你的节点引入一个remove方法呢?

class MySymbol {
    protected parent: MySymbol | undefined;
    protected children: MySymbol[];

    remove() {
        this.children = [];
        this.parent && this.parent.childRemoved(this);
    }

    childRemoved(child: MySymbol) {
        this.children.splice(this.children.indexOf(child), 1);
    }
}

(请注意,我将 Symbol 改为 MySymbol,否则会出现重复名称错误)

这种方法只在孩子只能有一个父母的情况下有效,否则这需要稍作改变。

编辑

唯一可能给你类似效果的方法是为你的 children 使用 WeakMap。
也可以阅读这里的答案:在 Javascript 中使用 WeakMaps 创建常规弱引用