JavaScript オブジェクトを適切に複製するにはどうすればよいですか?
P粉334721359
2023-08-23 12:26:59
<p>オブジェクト <code>x</code> があります。これをオブジェクト <code>y</code> としてコピーして、<code>y</code> への変更によって <code>x</code> が変更されないようにしたいと考えています。組み込み JavaScript オブジェクトから派生したオブジェクトをコピーすると、余分な不要なプロパティが作成されることに気づきました。私は独自のテキストで構築したオブジェクトの 1 つをコピーしているので、これは問題ではありません。 </p>
<p>JavaScript オブジェクトを適切に複製するにはどうすればよいですか? </p>
オブジェクトで Date、Function、Unknown、regExp、または Infinity を使用していない場合、非常に単純な行は
JSON.parse(JSON.stringify(object)) です。
については、この記事も参照してください。ディープ クローン作成機能も含まれています。
2022年更新
構造化クローニングと呼ばれる新しい JS 標準があります。多くのブラウザで動作します (「使用できますか 」を参照)。 リーリー
古い答えclone
列挙できないプロパティに加えて、非表示のプロパティを持つオブジェクトをコピーしようとすると、さらに厄介な問題に遭遇します。たとえば、メソッドを
Object.prototypeに追加する場合 (一部の回答が示唆しているように)、そのプロパティを明示的にスキップする必要があります。しかし、
Object.prototypeにその他のメソッドが追加されている場合や、知らない他の中間プロトタイプがある場合はどうなるでしょうか?この場合、コピーすべきではないプロパティをコピーしているため、
hasOwnPropertyメソッドを使用する必要があります。
prototype
洗練されたソリューションを探す際のもう 1 つの障害は、プロトタイプの継承を正しく設定するという問題です。ソース オブジェクトのプロトタイプがは関数の隠し属性です。さらに、オブジェクトのプロトタイプはプロパティ
__proto__を通じて参照されますが、これも非表示であり、ソース オブジェクトのプロパティを反復する for/in ループによってコピーされません。 __proto__ は Firefox の JavaScript インタプリタに固有であり、他のブラウザでは異なる可能性があると思いますが、アイデアは理解できますか。すべてが数えられるわけではありません。非表示のプロパティの名前がわかっている場合は、それをコピーできますが、それを自動的に検出する方法はわかりません。
Object
d1の場合は、
{}を使用して新しい汎用オブジェクトを作成するだけですが、ソース オブジェクトのプロトタイプが
Objectの場合は、子孫コード>、その場合、
hasOwnPropertyフィルターを使用してスキップされたプロトタイプ内の他のメンバー、またはそもそも列挙可能ではなかったプロトタイプ内の他のメンバーが失われます。解決策の 1 つは、ソース オブジェクトのコンストラクター プロパティを呼び出して初期コピー オブジェクトを取得し、その後プロパティをコピーすることですが、それでも列挙不可能なプロパティは取得できません。たとえば、
Datecode> オブジェクトは、そのデータを非表示メンバーとして保存します。 リーリー
の日付文字列は、
d2
より 5 秒後になります。あるDate
を別のDate
と同一にする方法は、setTime
メソッドを呼び出すことですが、これはDate
クラスに固有です。この問題に対する確実な普遍的な解決策はないと思いますが、間違っていることは幸いです。一般的なディープ コピーを実装する必要があったとき、私は最終的に妥協して、通常の
リーリーObject
、Array
、Date代码>、をコピーするだけでよいと考えました。 String代码>、Number代码>、または Boolean代码>。最後の 3 つのタイプは不変なので、変更されることを気にせずに浅いコピーを実行できます。さらに、
Object
またはArray
に含まれる要素も、このリストの 6 つの単純型の 1 つであると仮定します。これは次のようなコードで実行できます:オブジェクトと配列内のデータがツリー構造を形成している限り、前述の 6 つの単純な型には上記の関数で十分です。つまり、オブジェクト内の同じデータは 1 回だけ参照されます。例えば:### リーリー
これは JavaScript オブジェクトを処理できませんが、投げたものだけで動作すると考えない限り、多くの目的には十分かもしれません。