web-dev-qa-db-ja.com

OOP JavaScriptで循環参照を回避する方法は?

JavaScriptでエンティティフレームワークを使用しているときに問題が発生しました。テーブルと列の2つのクラスがあります

Class Table {
Columns: Column[]
}

Class Column {
Parent: Table
}

Baseクラスに実装した関数toJSON(テーブルと列の両方がBaseから継承)を使用するまで、すべてが正常に機能します。この関数は、インスタンスのすべてのプロパティを調べ、JSON文字列に解析するだけです。これは永続化を目的としています。しかし、この場合のtoJSONは、列からテーブルへ、そして列へ戻るループを永久に引き起こします。

そこにいる専門家がこれを手伝ってくれる?

2
Phương Lâm

あなたが説明したことから、循環参照はまったく必要ないので、あなたができる最善のことはそれを完全に取り除くことです。

columnクラスには、「tableA.colB」のようにテーブルと列を組み合わせて文字列を返すビルド関数があります。列がどのテーブルに属するかを知る必要があるのはそのためです。これらのエンティティはSQLステートメントの構築に使用されます。

これは、build関数がColumnクラスに属していないことを示しています。考えてみてください:データベースの単一の列がSQLステートメントの一部を構築するためのオブジェクトなのはなぜですか?おそらく、その目的のために実際に設計された完全に別のクラスでSQLの構築を行いたいでしょう。

class SQLBuilder {
    build: function(table, column) {
        return ... + table.name + "." + column.name + ...;
    }
}

何らかの理由でこれが選択肢にならない場合は、直接参照(「JSONを壊す」以外の実際の循環参照のほとんどの欠点がある)ではなく、親テーブルの名前を格納するなどの手段を講じることができます。 、またはカスタムシリアライゼーションロジックの実装(これは、保守が非常に面倒でエラーが発生しやすいコードです)ですが、十分な理由がない限り、そのようなことは行わないでください。

3
Ixrec

コメントで述べられているように、最も簡単な方法は、コメントで述べられているようにParentからColumn参照を削除することです。ほとんどの場合、必要に応じて、コードを変更して、テーブルと列の両方を(列だけでなく)ペアとして提供できます。

次の最も簡単な方法は、Parent内のColumnsの内容をオブジェクト参照から何らかの値のIDに変更することです。または、テーブルの一意のIDまたは名前を保持する文字列。つまり、テーブル全体にアクセスする必要がある場合、_column.Parent_の使用法は、インデックスまたは文字列を親に変換する方法を理解する関数にラップする必要があります。

テーブル名が一意であり、それが_column.Parent_から必要なすべてである場合、これらのフィールドを(循環)参照から別のオブジェクトへの参照から、テーブルの名前を識別する文字列に変換すると、最も効果的です。

次の方法は、ColumnタイプにカスタムtoJSON()を提供して、シリアル化のためにParentフィールドを変更し、参照からインデックスまたは文字列に変更することです上記;その後、これはJSON.stringify()の間にのみ発生し、そのフィールドのメモリ内での定期的な使用中は発生しません。もちろん、これを行うには、参照を理解し、それらをオブジェクトに変換するJSON.parse()の最中/後にreviver操作を作成またはシミュレートする必要もあります。

1
Erik Eidt