【先端チーズツリー】浅いコピー、深いコピー、Object.assign()の役割、クローンオブジェクト、複製配列

4817 ワード

【先端チーズツリー】浅いコピー、深いコピー、Object.assign()の役割
まず、Javascriptの基本的なデータタイプに戻らなければなりません.
値タイプ[ ]:数値Num、ブール値Boolean、文字列String、null、undefined.
基本タイプの値とは、スタックに保存されている簡単なデータセグメントです.基本タイプの値をコピーすると、新しいメモリ空間が開けられます.値を新しいメモリ空間にコピーして、くりを挙げます.
var a = 1;
var b = a;
a = 2;
console.log(a);//  2;
console.log(b);//  1;
参照タイプ[ ]:オブジェクト、配列、関数など.
タイプ値はヒープメモリに保存されているオブジェクトで、変数が保存されているのはそのメモリのアドレスを指しているだけで、参照タイプの値をコピーするときは、そのメモリを指すアドレスだけをコピーして、くりを挙げます.
var a={b:1}
var a2 = a;
a2.b = 2;
console.log(a)  //    {b: 2}
だから、深くコピーする問題が現れたのは、引用タイプのデータの浅いコピー特性を解決するためです.
オブジェクトの深度コピーを実現するいくつかの方法
  • JSON.parse()&JSON.stringfy()は、オブジェクトをそのJSON文字列表現形式に変換し、それらを解析してオブジェクトに戻す.これは簡単すぎると思いますが、効果的です.
    const obj = /* ... */;
    const copy = JSON.parse(JSON.stringify(obj));
    の利点は、ループオブジェクトがない場合、内蔵タイプを保持する必要がないということです.この方法を使うと、ブラウザをまたいで最も速いクローン性能が得られます.ここの欠点は、一時的に作成された文字列が大きいかもしれません.ただ、それを解析器に戻すためです.もう一つの欠点は,この方法は循環物体を扱うことができず,循環物体がしばしば発生することである.例えば、ツリー状のデータ構造を構築する場合、ノードの一つは親レベルを参照し、親レベルはまたそのサブレベルを参照する.
    const x = {};
    const y = {x};
    x.y = y; // Cycle: x.y.x.y.x.y.x.y.x...
    const copy = JSON.parse(JSON.stringify(x)); // throws!
    はまた、MapSetRegExpDateArrayBuffer、および他の内蔵タイプが、プログレッシブされている間に失われます.
  • MessageChannel&postMessage構造クローンアルゴリズムのこの方法の欠点は非同期である.これは大丈夫ですが、あるオブジェクトを同時にコピーする必要があります.
    function structuralClone(obj) {
      return new Promise(resolve => {
        const {port1, port2} = new MessageChannel();
        port2.onmessage = ev => resolve(ev.data);
        port1.postMessage(obj);
      });
    }
    
    const obj = /* ... */;
    const clone = await structuralClone(obj);
  • Array.slice()およびArray.concat()の方法は、ディープコピーに属しますか?
    これは全部めちゃくちゃになりました.インターネットで資料を探してやっと整理しました.
    一次元配列に対して:
  • arrayObj.slice(start,end)
    var arr1 = ["1","2","3"];
    var arr2 = arr1.slice(0);
    arr2[1] = "9";
    console.log("      :" + arr1 ); //1,2,3
    console.log("     :" + arr2 ); //1,9,3
  • arrayObj.co ncat(arr 1,arr 2…)
    var arr1 = ["1","2","3"];
    var arr2 = arr1.concat();
    arr2[1] = "9";
    console.log("      :" + arr1 ); //1,2,3
    console.log("     :" + arr2 );//1,9,3
  • 行列の中にオブジェクトが含まれていますか?
    var arr1 = [{"name":"weifeng"},{"name":"boy"}];//   
    var arr2 = [].concat(arr1);//    
    arr1[1].name="girl";
    console.log(arr1);// [{"name":"weifeng"},{"name":"girl"}]
    console.log(arr2);//[{"name":"weifeng"},{"name":"girl"}]
    
    var a1=[["1","2","3"],"2","3"],a2;
    a2=a1.slice(0);
    a1[0][0]=0; //  a1            
    console.log(a2[0][0]);  //    a2
    上記の2つの例から、配列内部の属性値は参照対象であるので、sliceとconcatを用いて対象配列のコピーは、全体的にコピーするかそれとも浅いコピーか、コピー配列の各値のポインタは同じ記憶アドレスを指すかが分かる.Array.slice()Array.concat()のこの2つの方法は、参照対象を含まない1次元配列の深度コピーにのみ適用される.
    Object.assign()方法及びオブジェクト拡張操作器...Object.assign()方法
    Object.assign()考察点はES 6において対象コピーを実現し、Object.assign()という関数についてここで詳しく説明しています.
    ES 6は、オブジェクトを統合/複製するためのObject.assign()の属性を提供する.
    Object.assign(target, source_1, ..., source_n)
    次は一例です.
    var o1 = { a: 1, b: 1, c: 1 };
    var o2 = { b: 2, c: 2 };
    var o3 = { c: 3 };
    
    var obj = Object.assign({}, o1, o2, o3);
    console.log(obj); // { a: 1, b: 2, c: 3 }
    Object.assignの方法は浅いコピーですか?それとも深いコピーですか?この例を見てください.
    function mutateDeepObject(obj) {
      obj.a.thing = true;
    }
    
    const obj = {a: {thing: false}};
    const copy = Object.assign({}, obj);
    mutateDeepObject(copy)
    console.log(obj.a.thing); // prints true 
    Object.assign(target, sources...)は簡単なコピー対象の方式であり、浅いコピーに属する.任意の数のソースオブジェクトが受け入れられます.主な役割は、それらの属性を列挙して割り当てられます.targetオブジェクト拡張操作器...オブジェクト拡張操作子を使用して、オブジェクト自体のエニュメレート・属性を新しいオブジェクトにコピーすることができます.
    const obj = { a: 1, b: 2, c:{d:'d'} }
    const shallowClone = { ...obj }
    shallowClone.a = 'a';
    shallowClone.c.d = '4';
    console.log(obj); // a: 1, b: 2, c: {d: "4"}}
    console.log(shallowClone); // a: "a", b: 2, c: {d: "4"}}
    他は対象のように見えますが、実質的には浅いコピーの方法です.
    const obj = { a: 1, b: 2, c:{d:'d'} }
    const shallowClone = Object.keys(obj).reduce((acc, key) => (acc[key] = obj[key], acc), {});
    shallowClone.a = 'a';
    shallowClone.c.d = '4';
    console.log(obj); // a: 1, b: 2, c: {d: "4"}}
    console.log(shallowClone); // a: "a", b: 2, c: {d: "4"}}