깊은 복사(Deep Copy)
연결된 노트와 함께 읽기
- 결론부터 말하자면 , 깊은 복사는 객체의 실제 값(원시 타입(Primitive type))을 복사한다.
- 원시 타입(Primitive type)을 복사할 때 그 값은 또 다른 독립적인 메모리 공간에 할당하기 때문에, 복사를 하고 값을 수정해도 기존 원시 타입(Primitive type)을 저장한 변수(Variable)에는 영향을 끼치지 않는다.
변수와 객체에서의 복사의 차이
- 실제 값을 복사하는 것을 깊은 복사라고 한다.
- 하지만 이것은 자료형을 깊은 복사한 것이다.
- 참조 타입(Reference Type)을 복사할 때는 변수(Variable)가 객체(Object)의 참조를 가리키고 있기 때문에 복사된 변수 또한 객체가 저장된 메모리 공간의 참조를 가리키고 있다.
깊은 복사 방법
- JSON.JSON.stringify()는 객체(Object)를 JSON(Java Script Object Notation) 문자열로 변환하는데 이 과정에서 원본 객체(Object)와의 참조가 모두 끊어진다.
재귀 함수를 구현한 복사
- 복잡하다는 것이 단점이다.
Lodash 라이브러리 사용
- 라이브러리를 사용하면 더 쉽고 안전하게 깊은 복사를 할 수 있다.
- 설치를 해야 한다는 점과 일반적인 개발에는 효율적이겠지만, 코딩 테스트에는 사용할 수 없다는 것이 단점이다.
structuredClone() 메서드 사용
- 비교적 최근에 추가된 바닐라 자바스크립트 메서드(Method)로 structuredClone()를 사용하면 한번에 깊은 복사를 할 수 있다.
// 깊은 복사 예시
const a = 'a';
let b = 'b';
b = 'c';
console.log(a); // 'a';
console.log(b); // 'c';
// 기존 값에 영향을 끼치지 않음
// 얕은 복사 예시
const a = { one : 1, two : 2 };
let b = a;
b.one = 3;
console.log(a); // { one: 3, two: 2 } 출력
console.log(b); // { one: 3, two: 2 } 출력
// 기존 값에 영향을 끼침
const object = {
a: "a",
number: {
one: 1,
two: 2,
},
arr: [1, 2, [3, 4]]
};
const copy = JSON.parse(JSON.stringify(object)); // 객체를 json변환하고 다시 json를 객체로 변환
copy.number.one = 3;
copy.arr[2].push(5);
console.log(object === copy); // false
console.log(object.number.one === copy.number.one); // false 깊은 복사를 했기 때문에
console.log(object.arr === copy.arr); // false
console.log(object); // { a: 'a', number: { one: 1, two: 2 }, arr: [ 1, 2, [ 3, 4 ] ] }
console.log(copy); // { a: 'a', number: { one: 3, two: 2 }, arr: [ 1, 2, [ 3, 4, 5 ] ] }
const object = {
a: "a",
number: {
one: 1,
two: 2,
},
arr: [1, 2, [3, 4]]
};
function deepCopy(object) {
if (object =** null || typeof object !** "object") {
return object;
} // 객체인지 배열인지 판단
const copy = Array.isArray(object) ? [] : {};
for (let key of Object.keys(object)) {
copy[key] = deepCopy(object[key]);
}
return copy;
}
const copy = deepCopy(object);
copy.number.one = 3;
copy.arr[2].push(5);
console.log(object === copy); // false
console.log(object.number.one === copy.number.one); // false
console.log(object.arr === copy.arr); // false
console.log(object); // { a: 'a', number: { one: 1, two: 2 }, arr: [ 1, 2, [ 3, 4 ] ] }
console.log(copy); // { a: 'a', number: { one: 3, two: 2 }, arr: [ 1, 2, [ 3, 4, 5 ] ] }
const deepCopy = require("lodash.clonedeep")
const object = {
a: "a",
number: {
one: 1,
two: 2,
},
arr: [1, 2, [3, 4]]
};
const copy = deepCopy(object);
copy.number.one = 3;
copy.arr[2].push(5);
console.log(object === copy); // false
console.log(object.number.one === copy.number.one); // false
console.log(object.arr === copy.arr); // false
console.log(object); // { a: 'a', number: { one: 1, two: 2 }, arr: [ 1, 2, [ 3, 4 ] ] }
console.log(copy); // { a: 'a', number: { one: 3, two: 2 }, arr: [ 1, 2, [ 3, 4, 5 ] ] }
const mushrooms1 = {
amanita: ["muscaria", "viros"],
}
const mushrooms2 = structuredClone(mushrooms1);
mushrooms2.amanita.push("pantherina");
mushrooms1.amanita.pop();
console.log(mushrooms2.amanita) // ['muscaria', 'viros', 'pantherina']
console.log(mushrooms1.amanita) // ['muscaria']