このトピックについては、インターネット上で多くの議論が行われています。私はさまざまな状況に応じて自分でそれらを整理しました。最終的には、ディープ コピーをほぼ完璧に実現することができました。皆さんの議論をお待ちしています。 1. 直接譲渡オブジェクトは参照型です。別のオブジェクトに直接割り当てられている場合は、単なる参照です。実際、2 つの変数は同じデータ オブジェクトを指します。1 つのオブジェクトのプロパティが変更されると、もう 1 つのオブジェクトのプロパティも変更されます。 例1、簡単な例: 人間1 = { id: 1, 名前: 「ハッピー」 }; human2 = human1; // ここでは直接代入です console.log(human1); // {id: 1, name: 'happy'} console.log(human2); // {id: 1, name: 'happy'} // human1 の名前を変更すると human2 の名前も変更されます。human1.name = "life"; console.log(human1); // {id: 1, 名前: 'life'} console.log(human2); // {id: 1, 名前: 'life'} 例 2: オブジェクトをパラメータとして渡すと参照も渡されます。 人間1 = { id: 1, 名前: 「ハッピー」 }; console.log(human1); // {id: 1, name: 'happy'} 関数 foo(人間) { // ここで人間オブジェクトの名前が変更されます human.name = "life"; } foo(human1); // オブジェクトは参照渡しです console.log(human1); // {id: 1, name: 'life'} 2. 浅いコピー浅いコピーでは、オブジェクトの最初のレイヤーのみがコピーされます。最初のレイヤーのプロパティ値がオブジェクトの場合、プロパティへの参照のみがコピーされます。 オブジェクト1 = { a: 1、 b: { // bはオブジェクト b1: 2 } }; object2 = Object.assign({}, object1); // これは浅いコピーであり、オブジェクト b の参照のみがコピーされます // a は通常の型であり、互いに影響しません object1.a = 10; コンソール.log(オブジェクト1.a); // 10 コンソール.log(object2.a); // 1 // b は相互に影響を与えるオブジェクトです。object1.b.b1 = 20; コンソール.log(object1.b.b1); // 20 コンソール.log(object2.b.b1); // 20 完全なコピーを実現するには、ディープ コピーを使用する必要があります。 3. ディープコピーSen コピーとは、1 つのレイヤーをコピーするだけでなく、その内部のレイヤー (オブジェクトの場合) もコピーする必要があることを意味します。 1. JSONオブジェクトメソッドオブジェクトが 上記の例を使用します。 オブジェクト1 = { a: 1、 b: { // bはオブジェクト b1: 2 } }; object2 = JSON.parse(JSON.stringify(object1)); // ディープコピー // a は通常の型なので互いに影響しません。object1.a = 10; コンソール.log(オブジェクト1.a); // 10 コンソール.log(object2.a); // 1 // b はオブジェクトなので互いに影響しません object1.b.b1 = 20; コンソール.log(object1.b.b1); // 20 コンソール.log(object2.b.b1); // 2 ここでのディープ コピーの原理は、実際にはオブジェクトを最初に
したがって、このメソッドは純粋な 2. 再帰コピーレイヤーごとにコピーする必要があるため、再帰的なアプローチを使用することは簡単です。次の実装を参照してください。 関数 deepCopy(ソース) { // オブジェクトまたは null でない場合は直接返します if (typeof source !== 'object' || source === null) { ソースを返します。 } ターゲットを{}とします。 // プロパティをトラバースしてコピーする for (let k in source) { if (!source.hasOwnProperty(k)) { 続く; } if (typeof source[k] === 'object') { // オブジェクトの場合は再帰的にコピーします target[k] = deepCopy(source[k]); 続く; } 記述子を Object.getOwnPropertyDescriptor(source, k); とします。 Object.defineProperty(ターゲット、k、記述子); } ターゲットを返します。 } オブジェクトはレイヤーごとにコピーされるため、コピーが完了した後、2 つのオブジェクトは互いに影響を与えず、メソッドもサポートされます。 オブジェクト1 = { a: 1、 b: { // bはオブジェクト b1: 2 }, f: function() { // f はメソッドです console.log(3); } }; object2 = deepCopy(object1); // ディープコピー。関数もコピーできます。 オブジェクト1.f(); // 3 オブジェクト2.f(); // 3 // b はオブジェクトなので互いに影響しません object1.b.b1 = 20; コンソール.log(object1.b.b1); // 20 コンソール.log(object2.b.b1); // 2 プロトタイプオブジェクトのコピー しかし、この方法にはまだ問題があります。つまり、プロトタイプ オブジェクトをコピーできないのです。これを少し改善してみましょう。 // プロトタイプもコピーされるように、let target = {}; を次のように変更します。let target = Object.create(Object.getPrototypeOf(source)); 以上です。例を使って確認してみましょう。 関数Human() { id = 1; } Human.prototype.bar = 関数() { console.log("バー"); }; human1 を新しい Human() にします。 人間2 = deepCopy(人間1); console.log("人間1", 人間1); console.log("human2", human2); 次の 2 つのオブジェクトのプロトタイプを見てみましょう。 プロトタイプ オブジェクトをディープ コピーします。 完璧なコピーです。 もちろん、この方法には問題があります。再帰レベルが深すぎると、スタックオーバーフローが発生しやすくなります。ただし、実際には、非常に大きなオブジェクトをコピーしないことも推奨されます。他の適切な解決策があるはずです。 参考資料: JS はディープコピーを実装します: https://www.cnblogs.com/dobeco/p/11295316.html 以下もご興味があるかもしれません:
|
>>: クロスブラウザの問題に対する 5 つの解決策 (要約)
これを理解するおそらく、他のオブジェクト指向プログラミング言語でもthis見たことがあり、これがコン...
1.ハードディスクを追加する2. パーティションの状態を確認します: fdisk -l 3. パーテ...
1. はじめに外部キー制約を使用するかどうかという話題は、すでに決まり文句になっています。学校では、...
ミックスインメソッド: ブラウザはコンパイルできません: 以前のバージョンのsassでは上記の記述方...
LAN 内のマシンは外部ネットワークにアクセスできますが、外部ネットワークは内部ネットワークにアクセ...
非常に便利な機能group_concat() について、マニュアルには次のように記載されています: ...
この記事では、シンプルなカルーセルを実装するためのJavaScriptの具体的なコードを参考までに紹...
Docker はコンテナに相当し、必要な動作環境に応じて対応する動作環境を構築できます。このとき、各...
<br />国内のウェブサイトが本格的に普及し、ユーザーエクスペリエンスに重点が置かれる...
JavaScriptは画像を表示したり非表示にしたりしますが、参考までに具体的な内容は次のとおりで...
Tomcat サーバーは、無料でオープン ソースの Web アプリケーション サーバーです。軽量のア...
使用シナリオ:ジャンプ パスは、傍受された URL に応じて動的に構成する必要があります。これは、イ...
Ubuntu 18のインストール中に、USBディスクからUbuntuのインストールを開始すると、mm...
目次序文異なるコンピュータ上の 2 つの Node.js プロセス間の通信TCPソケットの使用HTT...