以前は深いコピーと浅いコピーが頭の痛い問題だったので、この言葉を見ると不安になります。それで私は情報をチェックし、情報をチェックし、情報をチェックし続けました。。。幸いなことに、それは今では明らかです。私と同じ疑問を持っている人の助けになればと思い、そして今後私自身が忘れて心配しないようにしたいと思い、ここに書きます。浅いコピーと深いコピーの最大の違いは斜体の部分を参照してください。以下で 1 つずつ理解していきます。
1. コピーとは何ですか?
回答: コピーとは、オブジェクトのコピーまたはクローン作成とよく呼ばれるものです。コピーは浅いコピーと深いコピーに分けられます。
2. 浅いコピーとは何ですか?
回答: 浅いコピーはメモリ アドレスのコピーです。そのため、「コピーされた」と「元の」は同じメモリ アドレスを指します。これはオブジェクトへの単なる参照であり、コピーできるのは 1 つのレイヤーのみであり、サブオブジェクトコピーすることはできません。その結果、コピーの前後の 2 つのオブジェクトが相互に影響を及ぼし、たとえあなたが変更し、私が変更したとしても、これは実際の開発プロセスでは非常に悪いことです。それでも理解できない場合は、次の例を見てください。
1. 共通オブジェクト
var obj={
name:'du',
age:21,
borther:{
name:'rui',
age:12
}
};
var obj1 = obj;
obj1.sex='女';
console.log(obj1,obj);
//打印出结果为:
obj1:{name: "du", age: 21, borther: {…}, sex: "女"}
obj:{name: "du", age: 21, borther: {…}, sex: "女"}
obj1 が変化すると、それに応じて obj も変化することがわかります。これにより多くのことが制限されます。。。。
2. 配列オブジェクト
var arr=[1,2,3,{a:6}];
var arr1=arr.concat();
arr1[3].b=7;
arr[3].c=8;
console.log(arr,arr1);
//打印出结果为
arr: [1, 2, 3, {…}]0: 11: 22: 33: {a: 6, b: 7, c: 8}length: 4__proto__: Array(0)
arr1: [1, 2, 3, {…}]0: 11: 22: 33: {a: 6, b: 7, c: 8}length: 4__proto__: Array(0)
配列でも同じことが当てはまることがわかります。。。。。これは浅いコピーです。
3. ディープコピーとは何ですか?
回答: ディープ コピーは、オブジェクト内のサブオブジェクトを再帰的にコピーし、コピーすることです。コピー後、2 つのオブジェクトは互いに影響を受けません。これらは異なるアドレスを持ち、ヒープ内に異なるメモリを持つため、簡単にまとめると、値は同じですが、アドレスは異なります。以下に例を書きます。JSON.parse()/JSON.stringify() を使用するとより明確になります。
var obj={
name:'du',
age:21,
borther:{
name:'rui',
age:12
}
};
//JSON.stringify()是将json对象转换为字符串型,JSON.parse()是将字符串转换为json对象
var obj1=JSON.parse(JSON.stringify(obj));
obj1.sex='女';
obj.borther.sex='男';
console.log(obj1,obj);
//打印出来结果为
obj1:{name: "du", age: 21, borther: {…}, sex: "女"} //注意对象的属性
borther:{name: "rui", age: 12} //注意子对象borther的结果
obj: {name: "du", age: 21, borther: {…}} //注意对象的属性
borther:{name: "rui", age: 12, sex: "男"} //注意子对象borther的结果
このことから、obj1 が変化しても obj は変化せず、obj が変化しても obj1 は変化しないことがわかります。これはディープコピーです。
4.ディープクローンのカプセル化
これらを読んだ後、浅いコピー、深いコピー、およびそれらの違いについて理解する必要があります。しかし、欠点は、ディープ コピーでは json データの使用のみが確認されることなので、ディープ コピー メソッドをカプセル化できますか? 本当にカプセル化できます、はははははは、以下を見てみましょう
ディープコピーを導入する際には、まず頭の中で「どうやって、なぜ行うのか」という思考の枠組みを構築する必要があります。。。
1. オブジェクトを最初に通過する必要があることに疑いの余地はありません
2. 元の値かどうかの判定 typeof() -->object
3. 配列であるかオブジェクトであるかを判断します (メソッドには、instanceof / toString /constructor が含まれます)。
4. 対応する配列またはオブジェクトを作成します
5. 再帰
これらのアイデアを使用すると、コードを書くのがはるかに簡単になります
function deepClone(origin ,target){
var target = target||{}; //以防用户没传,默认是对象
for(var prop in origin){
//hasOwnProperty是用来判断某个属性是不是在对象自己的属性,它不会检测到原型链上去
if(origin[prop]!==null&&origin.hasOwnProperty(prop)){ //一定得确定对象上的属性不是原型链上的
if(typeof(origin[prop])=='object'){ //判断是不是原始值
//在不是原始值的情况下,判断是数组还是对象
target[prop] = Object.prototype.toString.call(origin[prop])=='[object Array]'?[]:{};
deepClone(origin[prop],target[prop]);
}else{
target[prop]=origin[prop];
}
}
}
return target;
}
var obj={
name:'du',
age:21,
borther:{
name:'rui',
age:12
}
};
var obj1=deepClone(obj,obj1);
obj1.sex='女';
obj.borther.sex='男';
console.log(obj1,obj);
//打印结果为
obj1: {name: "du", age: 21, borther: {…}, sex: "女"}
其中borther: {name: "rui", age: 12}
obj: {name: "du", age: 21, borther: {…}}
其中borther: {name: "rui", age: 12, sex: "男"}
このことから、それらは互いに影響を及ぼさないことがわかります。ディープ コピーによってカプセル化が完了します。