JS賦値、和深コピー(配列と対象の深浅コピー)の例を詳しく説明する。


本論文の例は、JS割当値、和深コピーの浅い(配列と対象の浅いコピー)について述べる。皆さんに参考にしてあげます。具体的には以下の通りです。
深度コピーや浅いコピーはObjectやArayのような参照データタイプに対してのみ使用されます。 
浅いコピー
基本タイプのデータをコピーしただけで、タイプデータを引用してコピーしても参照が発生します。このコピーを浅いコピーといいます。
コピーはオブジェクトを指すポインタだけをコピーし、オブジェクト自体をコピーしないで、新しいオブジェクトと同じメモリを共有します。しかし、深くコピーすると別のオブジェクトを作成します。新しいオブジェクトは元のオブジェクトとメモリを共有しないので、新しいオブジェクトを変更すると元のオブジェクトに変更されません。
割り当てと浅いコピーの違い
新しい変数にオブジェクトを割り当てると、そのオブジェクトのスタックの中のデータではなく、そのオブジェクトのアドレスが割り当てられます。つまり、2つのオブジェクトが同じ格納空間を指しており、どのオブジェクトが変更されても、実は変更された格納空間の内容であるため、2つのオブジェクトは連動している。
浅いコピーはビット単位のコピーオブジェクトで、新しいオブジェクトを作成します。このオブジェクトはオリジナルのオブジェクト属性値の正確なコピーです。属性が基本タイプなら、コピーは基本タイプの値です。プロパティがメモリアドレス(参照タイプ)であれば、コピーはメモリアドレスですので、オブジェクトの一つがこのアドレスを変更すると、他のオブジェクトに影響を与えます。すなわち、デフォルトコピーコンストラクタは、オブジェクトを浅いコピーでコピーするだけです。すなわち、オブジェクト空間だけをコピーして、リソースをコピーしません。
まず二つの例を見てみます。コントラストと浅いコピーは元のオブジェクトにどのような変化がありますか?

//     
var obj1 = {
   'name' : 'zhangsan',
   'age' :  '18',
   'language' : [1,[2,3],[4,5]],
};
var obj2 = obj1;
obj2.name = "lisi";
obj2.language[1] = [" "," "];
console.log('obj1',obj1)
console.log('obj2',obj2)

//    
var obj1 = {
   'name' : 'zhangsan',
   'age' :  '18',
   'language' : [1,[2,3],[4,5]],
};
var obj3 = shallowCopy(obj1);
obj3.name = "lisi";
obj3.language[1] = [" "," "];
function shallowCopy(src) {
   var dst = {};
   for (var prop in src) {
       if (src.hasOwnProperty(prop)) {
           dst[prop] = src[prop];
       }
   }
   return dst;
}
console.log('obj1',obj1)
console.log('obj3',obj3)

上記の例では、Obj 1は元のデータであり、Obj 2は割当操作で得られますが、Obj 3は浅いコピーで得られます。オリジナルデータに対する影響はよく分かります。具体的には下表をご覧ください。

1、Object.assign()Object.assign()方法は、任意の複数のソースオブジェクト自身のエニュメレート・属性を対象オブジェクトにコピーし、対象オブジェクトに戻ることができる。しかし、Object.assign()は、浅いコピーであり、コピーは対象の属性の参照であり、対象自体ではない。

var obj = { a: {a: "kobe", b: 39} };
var initalObj = Object.assign({}, obj);
initalObj.a.a = "wade";
console.log(obj.a.a); //wade
注意:objectが1階しかない時、深いコピーです。

let obj = {
   username: 'kobe'
   };
let obj2 = Object.assign({},obj);
obj2.username = 'wade';
console.log(obj);//{username: "kobe"}
 2、アラy.prototype.com()

let arr = [1, 3, {
   username: 'kobe'
   }];
let arr2=arr.concat();    
arr2[2].username = 'wade';
console.log(arr)
新しいオブジェクトを変更すると元のオブジェクトに変わります。

3、アラy.prototype.slice()

let arr = [1, 3, {
   username: ' kobe'
   }];
let arr3 = arr.slice();
arr3[2].username = 'wade'
console.log(arr);
同じように新しいオブジェクトを変更すると元のオブジェクトに変更されます。

Arayのsliceとconcat方法についての補足的な説明:Arayのsliceとconcat方法は元の配列を修正しないで、浅いものを返して元の配列の中の要素の新しい配列をコピーしただけです。
元の配列の要素は下記の規則に従ってコピーされます。

  • この要素が対象である場合(実際の対象ではない)、sliceはこのオブジェクトをコピーして新しい配列に引用します。両方のオブジェクトの参照は同じオブジェクトを参照しています。参照されているオブジェクトが変化すると、新しいものと元の配列のこの要素も変化します。

  • 文字列、数字およびブール値(String、NumberまたはBooleanオブジェクトではない)に対して、sliceはこれらの値を新しい配列にコピーする。他の配列でこれらの文字列または数字またはブール値を変更すると、他の配列に影響を与えません。
  • この話は分かりにくいかもしれません。例を挙げて、上の例を小さく修正します。
    
    let arr = [1, 3, {
       username: ' kobe'
       }];
    let arr3 = arr.slice();
    arr3[1] = 2
    console.log(arr,arr3);
    

    4.ES 6   
    let{b}=a    let  [...b) = a;//objectが1階しかない時は、深コピーです。
    コピー
    深度コピー:コンピュータで、コピーしたオブジェクトを保存するための新しいメモリアドレスを開発しました。属性内のすべての参照タイプの値は、基本タイプの値であるまで巡回します。 )
    実装
    1、JSON.parse(JSON.strigify()
    
    let arr = [1, 3, {
       username: ' kobe'
    }];
    let arr4 = JSON.parse(JSON.stringify(arr));
    arr4[2].username = 'duncan'; 
    console.log(arr, arr4)
    

    原理:JSON.strigifyで対象をJSON文字列に変換し、JSON.parse()で文字列を対象に解析していくと、新たな対象が誕生し、さらに対象は新たなスタックを開拓して、深度コピーを実現します。
    この方法は配列またはオブジェクトの深度コピーを実現できるが、関数を処理することはできない。
    
    let arr = [1, 3, {
       username: ' kobe'
    },function(){}];
    let arr4 = JSON.parse(JSON.stringify(arr));
    arr4[2].username = 'duncan'; 
    console.log(arr, arr4)
    

    これは、1つのJavaScript値(オブジェクトまたは配列)をJSON文字列に変換する方法であり、関数を受け入れることができないからである。
    2、手書きの再帰方法
    再帰的方法は深さクローンの原理を実現する。オブジェクトを遍歴し、配列を通して中まで基本的なデータタイプである。
    
     //             
       function checkedType(target) {
         return Object.prototype.toString.call(target).slice(8, -1)
       }
       //      ---  /  
       function clone(target) {
         //         
         //     result          
         let result, targetType = checkedType(target)
         if (targetType === 'object') {
           result = {}
         } else if (targetType === 'Array') {
           result = []
         } else {
           return target
         }
         //      
         for (let i in target) {
           //             。
           let value = target[i]
           //                 /  
           if (checkedType(value) === 'Object' ||
             checkedType(value) === 'Array') { //  /        /  
             //       value 
             result[i] = clone(value)
           } else { //   value              。
             result[i] = value;
           }
         }
         return result
       }
    
    関心のある友達はオンラインHTML/CSS/JavaScriptコードを使ってツールを実行できます。http://tools.jb51.net/code/HtmlJsRunは上記のコードの運行効果をテストします。
    JavaScriptに関する多くの内容に興味がある読者は、本駅のテーマを見てもいいです。「JavaScript配列操作技術のまとめ」、「JavaScriptはアルゴリズムと技術の総括を遍歴します。」、「javascript対象向け入門教程」、「JavaScript数学演算の使い方のまとめ」、「JavaScriptデータ構造とアルゴリズム技術のまとめ」および「JavaScriptエラーとデバッグテクニックのまとめ
    本論文で述べたように、JavaScriptプログラムの設計に役に立ちます。