JSの深さを素早く理解し、コピーしてすぐに使用できる

深いコピーと浅いコピーに関する JS の素早い理解

自我记录

平たく言えば、コピーとはコピーすることです Ps: この記事は単なる個人的な意見と要約です。異なる意見がある場合は、コメント欄で指摘して一緒に学ぶことができます! まず、理解したいのですが、 、私JS の基本についていくつかの知識ポイント知る
必要があると思います直接使用したい場合は、直接見てください(ダーク コピー) インクが非常に多い理由は、これはES6拡張演算子 (ライト)、ES6 メソッド (ライト)、シリアル化および逆シリアル化メソッド(ディープ)です。深拷贝浅拷贝4数据类型引用类型
4.14.24.3
4.1...
4.2Object.assign(target,sources)
4.3JSON.parse(JSON.stringify(对象))

1. JSのデータ型

1.1 基本的なデータ型 (7)

1.Number(数值,包含NaN)
2.String(字符串)
3.Boolean(布尔值)
4.Undefined(未定义/未初始化)
5.Null(空对象)
6.Symbol(独一无二的值,ES6 新增)
7.BigInt (任意精度格式的整数,能够表示超过 Number 类型大小限制的整数,ES10新增)

1.2 参照型

1.Object(包含Array、Function等)

1.3 基本データ型と参照型の違い

(1).基本データ型( に格納)

基本データ型は に保存されているデータ型を指します。これらは简单数据段,数据大小确定,内存空间大小可以分配直接保存されているため、直接アクセスできます。

(2).参照型( に格納)

参照データ型はエンティティ格納されますインタプリタが参照値を探すときは、まずオブジェクト内のアドレスを取得し、アドレスを取得した後、ヒープからエンティティを取得します。指针(一个地址)指针指向堆起始地址

2. メモリ内でのスタックとヒープ

2.1 スタックとは

先入れ後出し。関数パラメータ値やローカル変数値などを保存するために、オペレーティング システムによって自動的に割り当ておよび解放されます。データ構造内のスタックのように動作します。

2.2 ヒープとは何ですか?

キューの優先順位、先入れ先出し。動的に割り当てられた領域は、通常、プログラマによって割り当ておよび解放されます。プログラマが解放しない場合、プログラムの終了時に OS によって再利用される可能性があります。割り当て方法はリンク リストに似ています。

2.3 相違点の概要

個人的には、この記事の観点から理解しています。基本数据类型在栈里面存的是值引用类型在栈里面存的是一个指针(アドレスのような気がします)は、指向对应堆里面的这个地址浅いコピーと深いコピーに関係するために使用されます。

詳細な概要については、オンラインの他の記事を参照してください。

3. 浅いコピーと深いコピー

1. 代入とはコピーが与えられること基本数据类型を意味します栈中的值が、引用类型代入されるのは栈中对应堆的的地址と です不是堆中的数据つまり、2 つのオブジェクトは、同一个存储空间どちらのオブジェクトが変更されても、実際には変更された記憶領域の内容であるという事実を示しています。したがって、2 つのオブジェクトはリンクされています。一方が変更されると、もう一方も変更されます。影響を受ける。
2. したがって、基本的なデータ型の浅い/深いコピーはありません。

3.1 浅いコピー

前述したように、オブジェクトまたは配列を定義する場合、変数には のみが格納されます一个地址オブジェクトコピーを使用する場合、属性が对象またはの場合数组、このときに渡すのは のみです一个地址したがって、子オブジェクトがこの属性にアクセスすると、親オブジェクトが指すアドレスまで遡ることになります堆内存中。つまり、親オブジェクトと子オブジェクトが発生した場合、关联両方の属性値は同じになります指向同一内存空间联动
簡単な理解: 浅いコピーとは、データの 1 つのレイヤーのみをコピーすることです。
一般的な方法は...次のとおりです。Object.assign(target,sources)

3.2 ディープコピー

同一のオブジェクトが作成されます。新しいオブジェクトは元のオブジェクトとメモリを共有せず、新しいオブジェクトを変更しても元のオブジェクトは変更されません。

4. よく使用されるコピーを共有する 3 つの方法

4.1 ES6 スプレッド演算子 (浅いコピー)

次のような浅いコピーはありません。

  // 没有进行深拷贝
  let a = [1, 2, 3]
  let b = a
  a[0] = 100
  console.log(a) // [100, 2, 3]
  console.log(b) // [100, 2, 3]

...次のように浅いコピーを使用します。针对只有一层数据

  // 进行浅拷贝
  let a = [1, 2, 3]
  let b = [...a]
  a[0] = 100
  console.log(a) // [100, 2, 3]
  console.log(b) // [1, 2, 3]

2 次元配列などの多層データ構造は、この方法でのみ変更できます。第一层

  // 只拷贝了一层数据
  let a = [1, 2, 3, [40, 50]]
  let b = [...a]
  a[0] = 10
  a[3][0] = 400
  console.log(a)  // [10, 2, 3, [400, 50]]
  console.log(b)  // [1, 2, 3, [400, 50]]

4.2 ES6 Object.assign(ターゲット、ソース)(浅いコピー)

次のような浅いコピーはありません。

  // 没有进行深拷贝
  let a = [1, 2, 3]
  let b = a
  a[0] = 100
  console.log(a) // [100, 2, 3]
  console.log(b) // [100, 2, 3]

Object.assign次のように浅いコピーを使用します。针对只有一层数据

  // 进行浅拷贝
  let a = [1, 2, 3]
  let b = Object.assign([], a)
  a[0] = 100
  console.log(a) // [100, 2, 3]
  console.log(b) // [1, 2, 3]

2 次元配列などの多層データ構造は、この方法でのみ変更できます。第一层

  // 只拷贝了一层数据
  let a = [1, 2, 3, [40, 50]]
  let b = Object.assign([], a)
  a[0] = 10
  a[3][0] = 400
  console.log(a) // [10, 2, 3, [400, 50]]
  console.log(b) // [1, 2, 3, [400, 50]]


ここに画像の説明を挿入します

変更を避けたい場合はxx002を共有することはできず、bのヒープはxx003とxx004を使用していることもわかります。
ここに画像の説明を挿入します
当然、展開演算子は実装できません。

4.3 シリアライズとデシリアライズの方法(ディープコピー)

JSON.parse(JSON.stringify(对象))

  let a = [1, 2, 3, [40, 50]]
  let b = JSON.parse(JSON.stringify(a))
  a[0] = 10
  a[3][0] = 400
  console.log(a, 'a') // [10, 2, 3, [400, 50]]
  console.log(b, 'b') // [1, 2, 3, [40, 50]]

4.4 再帰(ディープコピー)

只考虑数据层面

 // 递归
 function fnDeepCopy(newObj, obj) {
    
    
     // 遍历对象
     for (key in obj) {
    
    
         // newObj[key] = obj[key] 拷贝一层
         // 如果obj[key] 是数组,又要重新遍历数组拷贝,在如果obj[key]是对象也要重新遍历拷贝,否则就直接拷贝一层
         if (obj[key] instanceof Array) {
    
    
             // 先判断数组,因为Array也是对象的一种
             newObj[key] = []
             fnDeepCopy(newObj[key], obj[key])
         } else if (obj[key] instanceof Object) {
    
    
             newObj[key] = {
    
    }
             fnDeepCopy(newObj[key], obj[key])
         } else {
    
    
             newObj[key] = obj[key]
         }
     }
 }

 let a = [1, 2, 3, [40, 50]]
 let b = []
 fnDeepCopy(b, a)
 a[0] = 10
 a[3][0] = 400
 console.log(a) // [10, 2, 3, [400, 50]]
 console.log(b) // [1, 2, 3, [40, 50]]

ここに画像の説明を挿入します
まとめるのは簡単ではありませんが、お役に立てれば幸いです。一緒に学び、進歩していけたら幸いです(いいねとコレクションがモチベーションです) 以上が私がよくやる2つの方法
です
。偉い人と共有します:ディープ JS ディープ コピー オブジェクト: https://www.jianshu.com/p/b08bc61714c7

おすすめ

転載: blog.csdn.net/zhgweb/article/details/130807952