ディープコピーとシャローコピーは主に属性がオブジェクト(参照型)のオブジェクトを対象としています。
1. 基本型と参照型の違い
1) 基本型:変数に対応するメモリ領域に値を格納する値型です。
2) 参照型: アドレス型です。
住所とは: 住所は数字です。住所を持つ目的は何ですか? それは見つけやすくすることです。なぜ誰もが自宅に固有の住所を持たなければならないのでしょうか? つまり、郵便物を発送するときに自宅がわかるということです。例: 初期のスーパーマーケットの袋保管グリッドには、各グリッドに番号が付いています。バッグを保管するとき、ウェイターはあなたの持ち物を特定のグリッドに置き、このグリッドの番号 (ブランド) を渡します。買い物が終わってバッグを受け取ったら、ウェイターに自分のブランド(番号付き)を伝えるだけで、ウェイターはあなたの番号に基づいてバッグを探してくれます。この番号はグリッドのアドレスです。メモリも同様で、各メモリには CPU が見つけやすいように番号が付けられています。そうでなければ、メモリの広大な海の中で、CPU はどのようにしてデータを見つけることができるでしょうか? 上記の変数 arr は参照型です arr に相当するメモリにはアドレスが格納されています 実際のデータはアドレスに相当するメモリ領域にあります 履歴書を記入するときと同じように、履歴書用紙に自宅の住所を書きますの住所。履歴書の自宅住所を書く場所がarrに相当します。この住所に基づいてあなたの家を見つけることができます。履歴書に自宅の住所を書く場所は、自宅を引用するのと同じです(目に見えない糸があなたの家を引っ張っていると想像できます。履歴書にこの目に見えない糸があり、手がかりをたどることで自宅を見つけることができます)。これが参照型と呼ばれる理由です。
2. 代入時の基本型と参照型のメモリ変更
実際、割り当てはコピーであると考えることができます。
-
基本タイプ:
-
参照タイプ:
arr[0] に値を割り当てると、arr と arr1 は同じアドレスを格納し、参照するデータが共有されるため、arr1[0] の値も変更されます。
上記に基づいてコードを追加すると: arr[0]=10; メモリは次のように変更されます。
3: 関数パラメータとしての基本型と参照型の違い
1. 関数のパラメータとしての基本型
2. 関数のパラメータとしての参照型:
4: ディープ コピーとシャロー コピーの実装:
いわゆるコピーとは譲渡のことです。ある変数を別の変数に代入するということは、変数の内容をコピーすることを意味します。あるオブジェクトの値を別のオブジェクトに代入すると、オブジェクトのコピーが作成されます。
1. 基本的な種類
なぜなら、基本型に値を代入する際にデータが代入されるからです(そのため、ディープコピーかシャローコピーの問題はありません)。
のように:
Var x = 100;
Var y = x; //此时x和y都是100;
y の値を変更したい場合、x の値は変更されません。
2. 参照型に問題があります
参照型に値が割り当てられている場合、割り当てられた値のアドレス (メモリに格納されている参照型変数の内容) を読み取ることが強く推奨されるため、上記の 2 番目の点 (代入中の基本型と参照型の間のメモリ内の変更) を読み取ることが強く推奨されます。 )を数回繰り返し、理解を深めます。このようにして、今後、参照型に関連するトピック (継承中、親クラスの属性は参照型であるなど) に遭遇した場合に問題はなくなります。
のように:
var arr1 = new Array(12,23,34)
Var arr2 = arr1;//这就是一个最简单的浅拷贝
arr2 によって参照されるデータを変更する場合: arr2[0]=100 の場合、arr1[0] の値も 100 になります。
その理由は、arr1 と arr2 が同じメモリ領域を参照しているためです (上記の 2 番目の点に反映されています)。
これは、arr1 のアドレスを arr2 にコピーするだけで、arr1 のデータはコピーしないため、最も単純な浅いコピーです。したがって、コピーの深さが十分ではありません。
3. json オブジェクト (参照型も) を使用して浅いコピーと深いコピーをデモンストレーションする
1) json オブジェクトを定義します (オブジェクトのプロパティもオブジェクトです)
var p = {
"id":"007",
"name":"刘德华",
"books":new Array("三国演义","红楼梦","水浒传")//这是引用类型
}
メモリマップ:
2). オブジェクト p のコピーを作成します。
(1) 浅いコピー
var p2 = {};
for(let key in p){
p2[key] = p[key];
}
p2.books[0] ="四国";
console.log(p2);
console.log(p);
コンソールに出力された結果 (p および p2 の book[0] が「Four Kingdoms」になりました):
メモリ:
(2) ディープコピー(暫定版)
var p2 = {};
for(let key in p){
if(typeof p[key]=='object'){
p2[key]=[];//因为,我上面写的是数组,所以,暂时赋值一个空数组.
for(let i in p[key]){
p2[key][i] = p[key][i]
}
}else{
p2[key] = p[key];
}
}
p2.books[0] ="四国";
console.log(p2);
console.log(p);
コンソールに出力された結果(p2のbooks[0]のみが「Four Kingdoms」になりました)
メモリ:
(3) ディープコピー(最終版)
3.1. ディープコピー - 属性がすべて json オブジェクトの場合は、再帰を使用します
// オブジェクトのプロパティがオブジェクト (参照型) の場合、プロパティのプロパティも参照型、つまり、ネストされたレイヤーが多数存在します。どうすればよいか、再帰するしかありません。
//次のオブジェクトをコピーする必要があります:
var p = {
"id":"007",
"name":"刘德华",
"wife":{
"id":"008",
"name":"刘德的妻子",
"address":{
"city":"北京",
"area":"海淀区"
}
}
}
//写函数
function copyObj(obj){
let newObj={};
for(let key in obj){
if(typeof obj[key] =='object'){//如:key是wife,引用类型,那就递归
newObj[key] = copyObj(obj[key])
}else{//基本类型,直接赋值
newObj[key] = obj[key];
}
}
return newObj;
}
let pNew = copyObj(p);
pNew.wife.name="张三疯";
pNew.wife.address.city = "香港";
console.log(pNew);
console.log(p);
3.2. ディープコピー - 属性が配列などの非キーと値のペアのオブジェクトである場合
これは個別に処理する必要があります。配列に自己複製関数を追加するか (これをお勧めします)、個別に判断する必要があります。
//给数组对象增加一个方法,用来复制自己
Array.prototype.copyself = function(){
let arr = new Array();
for(let i in this){
arr[i] = this[i]
}
return arr;
}
var p = {
"id":"007",
"name":"刘德华",
"books":new Array("三国演义","红楼梦","水浒传")//这是引用类型
}
function copyObj(obj){
let newObj={};
for(let key in obj){
if(typeof obj[key] =='object'){//如:key是wife,引用类型,那就递归
newObj[key] = obj[key].copyself();
}else{//基本类型,直接赋值
newObj[key] = obj[key];
}
}
return newObj;
}
var pNew = copyObj(p);
pNew.books[0] = "四国";
console.log(pNew);
console.log(p);