Hur bryter man starka referenscykler i TypeScript?


I en implementation har jag en trädliknande struktur med föräldra- och barnobjekt. Föräldrarna har en barnlista och barnen en referens till sina föräldrar, för att enkelt kunna navigera genom trädet. Nu undrar jag om en sådan struktur någonsin skulle kunna samlas upp av garbage collection, eftersom vi har starka referenscykler här (jag känner inte till svaga pekare i TypeScript).

Här är ett (superenkelt) exempel på en sådan struktur, även om jag tror att alla kan föreställa sig hur det skulle se ut:

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

Vad är det rekommenderade tillvägagångssättet för denna typ av datastruktur? Använd de (relativt) nya klasserna WeakMap eller WeakSet för att referera föräldrar (vilket låter fult)?

Svar #1

Det finns många sätt att representera träd, vilket som är bäst beror på vad du gör med din trädstruktur.
Om du är nöjd med det du har nu och bara bryr dig om skräpinsamling, varför inte införa en remove-metod för dina noder?

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);
    }
}

(notera att jag ändrade Symbol till MySymbol, annars får du ett fel med dubbla namn)

Detta tillvägagångssätt fungerar endast om ett barn bara kan ha en förälder, annars måste detta ändras lite.

Redigera

Det enda som kan ge dig något liknande är att använda en WeakMap för dina children.
Läs också svaret här: Skapa en vanlig svag referens i Javascript med hjälp av WeakMaps