[JavaScript] 객체 복사 (얕은 복사, 깊은 복사)
오늘은 JavaScript를 공부할 때 정리해두었던 객체 복사와 관련된 내용을 기록해보려한다.
1. 객체 복사 문제점
객체 변수는 메모리 어딘가에 저장되어 있는 객체를 참조할 수 있는 주소값이 저장된다.
아래 코드와 같이 A = B 와 같은 방식으로 객체 복사를 할 경우, 동일한 객체를 참조하는 주소 값을 복사하게 되어 각 객체 변수의 값을 변경할 경우 서로 영향을 주게되는 문제점이 발생한다.
이러한 문제점은 얕은 복사(Shallow copy), 깊은 복사(Deep Copy)를 통해 해결할 수 있다.
const user = {
name: "sally",
age: 23
};
const clone = user;
clone.name = "park";
console.log(clone.name); // output: "park"
console.log(user.name); // output: "sally"(x) -> "park"
2. 얕은 복사 (Shallow Copy)
단순 객체의 경우 반복문, Object.assign(), 전개 연산자를 이용해 얕은 복사가 가능하다.
아래 코드를 보면 얕은 복사의 경우 전개 연산자를 이용한 객체 복사의 코드가 간결하기 때문에 일반적으로 많이 사용한다.
1. 반목문 / Object.assign()을 이용한 얕은 복사
// 반복문을 이용한 객체 복사
const user = {
name: "sally",
age: 27
};
let clone = {};
for (let key in user) {
clone[key] = user[key];
}
clone.name = "park";
console.log(clone.name); //output: "park"
console.log(user.name); //output: "sally"
// Object.assign()을 이용한 객체 복사
const user = {
name: "sally",
age: 27
};
const clone = Object.assign({}, user);
clone.name = "park";
console.log(clone.name); // output: "park"
console.log(user.name); // output: "sally"
2. 전개 연산자를 이용한 얕은 복사
let user = {
name: "john",
age: 27
};
let clone = { ...user }; // {user.name, user.age}
clone.name = "park";
console.log(clone.name); // output: "park"
console.log(user.name); // output: "sally"
3. 깊은 복사 (Deep Copy)
객체 안에 또 다른 객체나 배열이 존재하는 경우 중첩된 부분은 얕은 복사로 복사되지 않는 문제점이 있다.
이러한 경우 JSON 객체 또는 외부 라이브러리 Lodash 등을 이용한 깊은 복사로 해결이 가능하다.
그리고 이번에 블로그를 작성하면서 추가로 공부하게 된 방법이 structuredClone() 이다.
1. JSON 객체를 이용한 깊은 복사
- stringify로 객체를 문자열로 변환해 원본 객체와의 참조가 끊기는 것을 활용한 것
const user = {
name: "sally",
age: 27,
sizes: {
height: 180,
weight: 70
}
};
// stringify: js object -> string, parse: string -> object
const clone = JSON.parse(JSON.stringify(user));
clone.sizes.height = clone.sizes.height + 1;
clone.sizes.weight = clone.sizes.weight - 1;
console.log(clone.sizes.height); // output: 181
console.log(clone.sizes.weight); // output: 69
console.log(user.sizes.height); // output: 180
console.log(user.sizes.weight); // output: 70
2. structuredClone() 를 이용한 깊은 복사
- 아래 코드와 같이 structuredClone 안에 복사할 객체 변수만 넣어주면 되기 때문에 매우 간단하게 복사가 가능하다.
- 지원 타입 / 기능 제한은 아래 MDN 공식문서에 확인 가능하다.
https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
The structured clone algorithm - Web APIs | MDN
The structured clone algorithm copies complex JavaScript objects. It is used internally when invoking structuredClone(), to transfer data between Workers via postMessage(), storing objects with IndexedDB, or copying objects for other APIs.
developer.mozilla.org
const user = {
name: "sally",
age: 27,
sizes: {
height: 180,
weight: 70
}
};
const clone = structuredClone(user);
clone.sizes.height = clone.sizes.height + 1;
clone.sizes.weight = clone.sizes.weight - 1;
console.log(clone.sizes.height); // output: 181
console.log(clone.sizes.weight); // output: 69
console.log(user.sizes.height); // output: 180
console.log(user.sizes.weight); // output: 70
4. 후기
오늘도 이전에 정리 해놓았던 것을 블로그에 기록하기 위해 공부를 하다보니 새로운 것을 공부하게 되었다. 블로그에 옮기면서 복습도 하고 새로운 것을 알게되는 것이 기술 블로그의 가장 큰 장점인 것같다.