shallow copy , deep copy
16977 ワード
shallow copy
繰り返し文でオブジェクトの値をコピーします.オブジェクトの値がオブジェクトの場合、オブジェクトのアドレスがコピーされます.
以前は原始資料型と参考資料型を学び、原始資料型の複製値、参考資料型の複製アドレスを学んだ.
//원본이 원시자료형인 경우
let primitive = 10;
let copiedPri = primitive;
copiedPri = 20; //copiedPri에 20 재할당
copiedPri; //20
primitive; //10
//원본이 참조자료형인 경우
const arr = [1,2,3];
const copiedArr = arr; //arr의 주소가 복사된다.
copiedArr.push('추가');
copiedArr; //[1,2,3,'추가']
arr; //[1,2,3,'추가']
そこで、参考資料型の「値」だけをコピーする方法も学びました.値はslice()、assign(ターゲット、ソース)、spread演算子のみでコピーできます.
Array.prototype.slice
const arr = [1,2,3];
const copiedArr = arr.slice();
copiedArr.push('추가');
copiedArr; //[1,2,3,'추가']
arr; //[1,2,3]
sliceメソッドを使用すると、「値」がコピーされたと判断できます.したがって、コピーにエンティティを追加または削除しても、元のエンティティには影響しません.ただし、次の場合、コピーを変更すると元のコピーも変更されます.
const arr = [1,2,3,[4]];
const copiedArr = arr.slice();
copiedArr[3].push('추가');
copiedArr; //[1,2,3,[4,'추가']]
arr; //[1,2,3,[4,'추가']]
上の状況で確認したようにArrayprototype.sliceのソースがネストされた構造(配列に配列がある構造)の場合、ネストされたエンティティを「値」にコピーするのではなく、アドレスがコピーされます.すなわち,sliceは浅いコピー(浅いコピー)を実行し,すべての値を独立してコピーすることはできない.spread operator
ES 6構文を使用して追加された拡張オペレータは、比較的簡単にコピーできます.
拡張オペレータが呼び出されると、内部で反復-ループが実行されます.オブジェクトに対して繰り返し文を実行できることは、オブジェクトに[Symbol.iterator]Propertyがあることを意味します.つまり、オブジェクトに[Symbol.iterator]属性がある場合、そのオブジェクトは繰り返し文を実行できます.
const a = [1,2,3];
const b = [...a];
b; //[1,2,3]
//내면에서 일어나는 과정
if(![Typeof(a) is Iterable)){
throw TypeError
}
const b = [];
for(let i=0;i<a.length;i++){
b.push(b[i]);
}
オブジェクトに[Symbol.iterator]propertyがあると判断した場合、forは文を繰り返し、要素を1つずつ移動します.移入要素の深さは1−dptである.したがって、slice演算子とspread演算子は、内部で重複文を実行し、配列またはオブジェクトが段落である場合、その段落が指すアドレスをコピーします.
Object.assign
//Copy
const obj = {a:1};
const copy = Object.assign({},obj);
console.log(copy); //{a:1}
console.log(obj===copy); //false
//Merge -기존 객체에 합치기
const obj1 = {a:1};
const obj2 = {b:2};
const obj3 = {c:3};
const merge1 = Obejct.assign(obj1,obj2,obj3);
console.log(merge1); //{a:1, b:2, c:3}
console.log(obj1); //{a:1, b:2, c:3}
//Merge -빈 객체에 합치기
const obj4 = {d:4};
const obj5 = {e:5};
const obj6 = {f:6};
const merge2 = Object.assign({},obj4,obj5,obj6);
console.log(merge2); //{d:4, e:5, f:6}
console.log(obj4); //{d:4}
//Nested Object가 있는 객체 복사하기
const original = {
name: 'kim',
age: 20,
city: 'seoul',
todos: ['study','exercise','clean','wash']
}
const copied = Object.assign({},original);
copied.todos.push('추가');
console.log(copied.todos); //['study','exercise','clean','wash', '추가']
console.log(original.todos); //['study','exercise','clean','wash', '추가']
Object.assign(ターゲット、ソース)もプロパティの値をコピーするので、ソースオブジェクトのキー値がオブジェクトへの参照(オブジェクトまたは配列の場合)である場合、参照がコピーされます.言い換えれば、slice、spread構文、Object.assignはいずれも浅いコピーを実行します.
deep copy
浅いコピーからNestedオブジェクトへの参照をコピーするのとは異なり、Nestedオブジェクトは新しいメモリ領域を取得し、コピーに新しい参照を持たせます.
キー値が参照の場合、参照のみコピーできますか?そうではありません.限られているが最も簡単な方法はJSONオブジェクトを使用することである.
JSON.parse & JSON.stringify
JSON.stringgifyを使用して配列を文字列に変更し、JSONを再開します.parseを使用してオブジェクトを置き換えます.
ここで文字列に変換する理由は、JavaScriptでは文字列が他の言語とは異なり、可変属性を持つ元のデータ型(primitive datatype)であるため、参照ではなく値そのものが格納されるためである.後で並べ替えるとnested objectにも新しい参照があります.配列を一瞬凍結(文字列)して融解(配列)したいなら、簡単なはずです.
したがって、上記の手順でアレイをコピーすると、レプリカで変更しても元のアレイは変更されないことを確認できます.
プロセスを一つ一つまとめてみましょう.
参考資料:深いコピーと浅いコピーの深い物語
Javascript: shallow and deep copy
Reference
この問題について(shallow copy , deep copy), 我々は、より多くの情報をここで見つけました https://velog.io/@kaitlin_k/얕은-복사와-깊은-복사テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol