この記事ではJavaScriptの基本であるディープコピーとシャローコピーについて説明します。

この記事ではJavaScriptの基本であるディープコピーとシャローコピーについて説明します。

コピー(クローン、複製などとも呼ばれる)ですが、ディープコピーとシャローコピーに分けられます。

実際、この問題は理解してみれば非常に簡単なこともあります。理解してみないと少し混乱するかもしれませんが、クロージャよりもはるかに理解しやすいです。

この概念はなぜ存在するのでしょうか?例を挙げてみましょう。

var 人 = {
    名前:"張三",
    年齢:22
}
var person1 = 人;
コンソールにログ出力します。
コンソールにログ出力します。

ここに画像の説明を挿入

コピーはできるようですが、person1の属性値を操作すると、personの属性値も変わってしまいます。

person1.name="李思";
コンソールにログ出力します。
コンソールにログ出力します。

ここに画像の説明を挿入

実は、これは非常に簡単に理解できます。つまり、上記の 2 つのオブジェクトのポインター アドレスは、スタック メモリ内の同じ場所を指しています。先ほど参照データ型について説明したときに、参照データ型とは何かを説明しました。

補充:

Object.property と object[property] は、実際にはどちらも操作オブジェクトの属性値であり、書き方が異なるだけです。

つまり、このポインタの割り当て方法はコピーではありません。では、コピーとは何でしょうか? それは、新しいオブジェクトがオブジェクトのすべてのプロパティを使用するが、それらが互いに影響を受けないことを意味します。

これを理解すると、コピーの本質は、オブジェクトのプロパティを新しいオブジェクトに周期的に割り当てることであることがわかります。

では、なぜ浅いコピーと深いコピーが存在するのでしょうか? 正直なところ、浅いコピーと深いコピーの間に本質的な違いはあるのでしょうか?

実際のところ、本質的な違いはありません。最大の違いは、コピー処理で考慮される条件と属性の種類です。

いつものように、まずはコードを見てみましょう

浅いコピー

var 人 = {
    名前:"張三",
    年齢:22
}
var person1 = {};
for(キーは人){
    console.log(キー);
    person1[キー]=person[キー];
}
コンソールにログ出力します。
コンソールにログ出力します。

ここに画像の説明を挿入

person1.name="李思";
コンソールにログ出力します。
コンソールにログ出力します。

ここに画像の説明を挿入

互いに影響がないことがわかりますが、新たな問題が発生します。つまり、person オブジェクトの属性はすべて基本データ型ですが、参照型の場合はどうなるでしょうか。たとえば、配列、オブジェクトなどでしょうか?

var 人 = {
    名前:"張三",
    年齢:22歳
    息子:
        長男:「張達茂」
    }
}
var person1 = {};
for(キーは人){
    console.log(キー);
    person1[キー]=person[キー];
}
コンソールにログ出力します。
コンソールにログ出力します。

ここに画像の説明を挿入

次に、person1 の send 属性を変更します。

person1.son={firstSon:"李達敖"};
console.log(人);
コンソールにログ出力します。

ここに画像の説明を挿入

お互いに影響を及ぼしていないように思えませんか?しかし、前述したように、object.property = は person1.son のプロパティを書き換えて割り当てることと同等であり、2 つのアドレスが異なるため、お互いの参照の影響は自然に切断されます。しかし、次の変更についてはどうでしょうか?

person1.son.secondeSon="李 達敖";
コンソールにログ出力します。
コンソールにログ出力します。

ここに画像の説明を挿入

意外であろうとなかろうと、予想外であろうとなかろうと、それらは互いに影響を及ぼし合います。このとき、新しい操作、つまりディープコピーが必要になります。簡単に言えば、属性値を参照型に変更することができます。

補充:

personのプロトタイプに属性値がある場合、それもperson1で取得され、person1に割り当てられます。これは前にも触れました。その場合、hasOwnPropertyを使用して、自分の属性値に属するかどうかを判定します。

ディープコピー

実際、ディープ コピーとシャロー コピーの違いは、属性値の種類を考慮するだけなので、もうほぼ理解できたと思います。

// 前述の通り、プロトタイプ上の値もコピーされます。便宜上、オブジェクトのプロトタイプチェーンを直接使用し、最後にオブジェクトにプロパティを追加します。
Object.prototype.address="推測";
var 人 = {
    名前:"張三",
    年齢:22歳
    息子:
        長男:「張達茂」
    }
}
strtype=Object.prototype.toString;
var person1 = {};
// 便宜上、ここでは再帰メソッドを使用します function coleFun(origin,target){
 // ターゲットオブジェクトが属性を持たないようにします target=target||{}
    for(キー in origin){
        (origin.hasOwnProperty(キー)) の場合 
         if(strtype.call(origin[key])=="[object オブジェクト]"){
            ターゲット[キー]={};
            ターゲット[キー]=coleFun(起点[キー],ターゲット[キー])
         }それ以外{
            ターゲット[キー]=オリジン[キー];
          }   
    }
    ターゲットを返します。
}
person1=coleFun(人,人1)
コンソールにログ出力します。
コンソールにログ出力します。

ここに画像の説明を挿入

結果を見て問題がなければ、属性値を変更してみてください

person1.son.secondeSon="李 達敖";
コンソールにログ出力します。
コンソールにログ出力します。

ここに画像の説明を挿入

今のところ問題はないようです。

いわゆるディープコピーとシャローコピーとは、簡単に言えば、属性値が参照型であるかどうかを考慮してコピーすることです。上記のコードが理解できない場合は、参照データと基本データの違い、これが何を指すのか、データ型をどのように判別するのかを確認する必要があるかもしれません。これについては以前の記事で説明しましたので、ご覧ください。

補充する

コメント欄で、JavaScript で JSON メソッドを使用してデータをコピーする場合、ディープ コピーですか、それともシャロー コピーですかと友人が質問しました。

実際、これは証明するのが非常に簡単です。参照データ型のオブジェクトをコピーし、それらが互いに影響するかどうかを判断するだけです。

まず、2 つのメソッドとその機能を見てみましょう。

方法効果
JSON.parse() JSON文字列を JavaScript オブジェクトに変換するために使用されます。
JSON.stringify() JavaScript 値をJSON文字列に変換するために使用されます。

次に、コードは次のことを示します。

var 人 = {
    名前:"張三",
    年齢:22歳
    息子:
        長男:「張達茂」
    }
}
var str = JSON.stringify(人);
var person1 = JSON.parse(str);
コンソールにログ出力します。
コンソールにログ出力します。

ここに画像の説明を挿入

少なくともコピーした結果は問題ないようです。

では、それらが互いに影響し合うかどうかをテストしてみましょう

person1.son.secondeSon="李 達敖";
コンソールにログ出力します。
コンソールにログ出力します。

ここに画像の説明を挿入

相互影響がないことがわかります。JOSN を介してコピーすることは、実際には JavaScript の一般的な方法です。結局のところ、自分で書くよりもはるかに便利です。その本質は、オブジェクトを JSON 形式の文字列に変換し、その文字列を通じてオブジェクトを生成することなので、これもディープ コピーです。

要約する

この記事はこれで終わりです。皆さんのお役に立てれば幸いです。また、123WORDPRESS.COM のその他のコンテンツにも注目していただければ幸いです。

以下もご興味があるかもしれません:
  • JavaScriptの浅いコピーと深いコピーについての簡単な説明
  • js における浅いコピーと深いコピーの詳細な説明
  • JSのディープコピーとシャローコピーの詳しい説明
  • JS の配列のディープコピーの実装方法の分析
  • JavaScript ディープコピーのいくつかの状況のまとめ

<<:  ウェブページ読み込み時に左右にジャンプする原因の分析と解決

>>:  CentOS8 システムをベースにした Gitlab を構築するために Docker を使用する詳細なチュートリアル

推薦する

JS クロスドメイン ソリューション React 構成 リバース プロキシ

クロスドメインソリューションjsonp (get をシミュレート) CORS (クロスオリジンリソー...

CentOS7.4 で JDK1.8 をインストールするためのグラフィカル チュートリアル

Linux インストール JDK1.8 手順1. CentOS に独自の openJDK があるかど...

MySQL バックアップ スクリプトの書き方

序文:データベースのバックアップの重要性は、特にデータの損失が深刻な結果を招く可能性がある実稼働環境...

Linux 上の Vim で色とテーマを変更する方法

Vim は Linux でよく使用されるテキスト エディターです。 Vim は、Sublime や ...

Nginx ロケーション設定のチュートリアル (ゼロから)

基礎位置の一致順序は、「最初に正規表現に一致し、次に共通表現に一致」です。実際のロケーションの一致順...

React+Antdはテーブルの追加、削除、変更の例を実装します

目次テーブル/index.jsテーブル/モデル/index.jsテーブル/モデル/モジュール/bas...

Vue + Axios リクエストインターフェース方式とパラメータ渡し方式の詳しい説明

目次1. リクエストを取得する: 2. 投稿リクエスト: 3. 拡張と補足Vue スキャフォールディ...

Node.js ファイルのコピー、フォルダの作成、その他の関連操作

NodeJS は次のファイルをコピーします:通常、小さなファイルのコピー操作では、ストリーム パイプ...

MySQL シャーディングの詳細

1. ビジネスシナリオの紹介MySQLを使用する電子商取引システムがあるとします。大量のデータを保存...

Node.js の TCP 接続処理のコア プロセス

数日前、友人と Node.js の epoll とリクエスト処理に関する知識を交換しました。今日は、...

MySQL マスタースレーブレプリケーションの実践の詳細説明 - ログポイントに基づくレプリケーション

ログポイントベースのレプリケーション1. マスターデータベースとスレーブデータベースに専用のレプリケ...

MySQL 8.0.18はデータベースにユーザーを追加し、権限を付与します

1. データベースにログインするには、rootユーザーを使用することをお勧めします。 mysql -...

Vueドロップダウンメニューのコンポーネント開発の詳細説明

この記事の例では、Vueドロップダウンメニューのコンポーネント開発の具体的なコードを参考までに共有し...

Flexレイアウトを使用してdiv内のサブ要素を垂直方向に中央揃えする例

1. Flex は Flexible Box の略で、「柔軟なレイアウト」を意味し、ボックス モデル...

MySQL パフォーマンス最適化のヒント

MySQL パフォーマンスの最適化MySQL はインターネット企業で広く使用されており、MySQL ...