자바스크립트는 기본적으로 얕은 복사
를 구현하게끔 되어 있습니다. 만약 깊은 복사
가 필요한 경우 여러 차선책들과 라이브러리에 의존해야 했습니다.
structuredClone()
이라는 함수가 Web API
로 지원되기 시작했습니다.
객체 변수는 메모리 어딘가에 저장되어 있는 객체를 참조할 수 있는 값을 저장하고 있습니다.
따라서 객체를 단순하게 변수 할당 방식으르 설정하는 경우, 동일한 객체를 참조하며 사실상 동일한 하나의 "객체"를 가리키게 됩니다.
1차원적인 단순 객체의 경우 비교적 간단하게 복사할 수 있습니다. 대표적으로 Object.assign
과 spread operator
를 이용하는 방법이 있습니다.
const clonedCat = {
name: 'cookie',
age: 2,
};
const clonedCat = Object.assign({}, cat); // or {...cat}
clonedCat.age = 3;
console.log(cat); // { name: 'cookie', age: 2 }
console.log(clonedCat) // { name: 'cookie', age: 3 }
하지만 객체 내부에 또 다른 객체가 있거나 배열이 존재하는 등의 경우엔 해당 부분은 여전히 원본의 내용을 참조하게 됩니다.
const cat = {
profile: {
name: 'cookie',
age: 2,
},
butler: '김메조',
}
const clonedCat = {...cat};
clonedCat.profile.age = 3;
clonedCat.butler = '김미디어';
console.log(cat); // { profile: { name: 'cookie', age: 3 }, butler: '김메조' }
console.log(clonedCat) // { profile: { name: 'cookie', age: 3 }, butler: '김미디어' }
이러한 복잡한 객체 구조에 대한 복사를 위해서는 깊은 복사를 해야 합니다.
JSON.stringify()
와 JSON.parse()
를 사용하여 객체 -> 스트링 -> 객체
의 변환 과정을 통해 깊은 복사를 수행할 수 있습니다.
제한 사항
- Recursive data structures (연결 리스트, 트리 구조 ...)
- Built-in types (Date, Map, Set, RexExp ...)
- Functions
const cat = {
profile: {
name: 'cookie',
age: 2,
},
butler: '김메조',
}
const clonedCat = JSON.stringify(JSON.parse(cat));
const cat = {
profile: {
name: 'cookie',
age: 2,
},
butler: '김메조',
}
const clonedCat = _.cloneDeep(cat);
structuredClone()
은 JSON.stringify()
의 많은 단점을 해결해줍니다. 순환되는 데이터 구조를 처리할 수 있고, 내장 데이터 타입을 지원할 수 있으며 일반적으로 더 강력하고 더 빠릅니다.
const cat = {
profile: {
name: 'cookie',
age: 2,
},
butler: '김메조',
}
const clonedCat = structuredClone(cat);
제한 사항
- 프로토타입: 클래스 인스턴스와 함께 사용하는 경우,
structuredClone()
이 프로토타입 체인을 폐기하므로 반환 값은 일반 객체가 됩니다.- Functions
- DOM 노드