오늘은 얕은복사와 깊은복사의 차이점에 대해 알아보려고 한다.
우선 얕은복사와 깊은복사의에 대해 알아보기 전에 참조에 관한 개념을 이해해야한다.
참조란?
let 강동욱 = { name: '강동욱', age: 26, job: 'frontEndDeveloper' }
let 손흥민 = 강동욱; // 강동욱과 손흥민은 참조관계가 된다.
손흥민.name = '손흥민';
손흥민.age = 30;
손흥민.job = 'soccer player'
console.log(손흥민); // {name: '손흥민', age: 30, job: 'soccer player'}
console.log(강동욱); // {name: '손흥민', age: 30, job: 'soccer player'}
위처럼 참조관계가 되면 손흥민의 속성(name, age, job)을 바꾸면 강동욱의 속성도 바뀌게 된다. 이럴 경우 내가 원하지 않는 강동욱의 속성도 바뀌게 되니 좋지 않다. 강동욱의 속성이 안바뀌게 할려면 어떻게 해야할까??
이때 사용하는 것이 복사이다. 복사에는 얕은복사와 깊은복사가 있다. 우선 얕은복사 부터 알아보자.
얕은복사
let 강동욱 = { name: '강동욱', age: 26, job: 'frontEndDeveloper', hobby: ['coding', 'game'] }
let 손흥민 = { ...강동욱 }; // 얕은복사를 한 것!
손흥민.name = '손흥민';
손흥민.age = 30;
손흥민.job = 'soccer player'
console.log(손흥민);
// {name: '손흥민', age: 30, job: 'soccer player', hobby: ['coding', 'game']}
console.log(강동욱);
// {name: '강동욱', age: 26, job: 'frontEndDeveloper', hobby: ['coding', 'game']}
위 처럼 얕은 복사를 하면 손흥민의 속성을 바꾸어도 강동욱의 속성은 바뀌지 않는다. 내가 원하는 상황이다. 아직 hobby를 안바꿔봤다.
hobby도 한번 바꿔보자.
let 강동욱 = { name: '강동욱', age: 26, job: 'frontEndDeveloper', hobby: ['coding', 'game'] }
let 손흥민 = { ...강동욱 }; // 얕은복사를 한 것
손흥민.name = '손흥민';
손흥민.age = 30;
손흥민.job = 'soccer player';
손흥민.hobby[0] = 'soccer';
손흥민.hobby[1] = 'watching movie';
console.log(손흥민);
// {name: '손흥민', age: 30, job: 'soccer player', hobby: ['soccer', 'watching movie']}
console.log(강동욱);
// {name: '강동욱', age: 26, job: 'frontEndDeveloper', hobby: ['soccer', 'watching movie']}
여기서 얕은복사의 문제점이 발생한다. 분명 복사를 했는데, 강동욱의 hobby도 같이 바뀐다.. 왜일까??
왜냐하면 hobby속성은 아직 참조 관계이기 때문이다. 분명 얕은 복사를 했는데 왜 아직 참조 관계일까??
얕은복사는 객체의 겉 껍데기( { } ) 만 복사하고, 내부는 참조관계가 유지된다. 이게 무슨말이냐면
let 손흥민 = { ...강동욱 }; 에서 빨간색만 복사가 된다는 뜻이다. 내부는 참조관계가 유지된다.
내부 name,age,job속성의 값은 원시타입이니까 참조관계라는 개념이 없기 때문에 참조관계가 안생긴것이고,
hobby속성의 값에 배열은 참조타입이므로 참조관계가 생기는 것이다. 그러므로 손흥민의 hobby속성과 강동욱의 hobby속성은 참조관계인 것이다.
그렇다면 우리가 원하는 동작을 구현하려면 내부까지 복사 해야하는데
즉, 바꿔말하면 내부까지 참조관계를 끊어야한다.
내부까지 어떻게 복사할까? 이때 사용하는 것이 깊은복사이다.
깊은복사
깊은복사를 하는방법은 여러가지이지만, 가장 간단한 방법을 알아보자. 바로 JSON.parse와 JSON.stringify를 이용하는것이다.
let 강동욱 = { name: '강동욱', age: 26, job: 'frontEndDeveloper', hobby: ['coding', 'game'] }
let 손흥민 = JSON.parse(JSON.stringify(강동욱)); // 깊은복사 한 것!
손흥민.name = '손흥민';
손흥민.age = 30;
손흥민.job = 'soccer player';
손흥민.hobby[0] = 'soccer';
손흥민.hobby[1] = 'watching movie';
console.log(손흥민);
// {name: '손흥민', age: 30, job: 'soccer player', hobby: ['soccer', 'watching movie']}
console.log(강동욱);
// {name: '강동욱', age: 26, job: 'frontEndDeveloper', hobby: ['coding', 'game']}
위 코드와 같이 강동욱의 hobby은 바뀌지않은것을 볼 수 있다. 우리가 원하는 복사를 완벽하게 한 것이다.
정리
얕은 복사는 겉 껍데기만 참조관계가 끊기는것이고, 깊은 복사는 전부 참조관계가 끊기는 것이다.
'Front end > JavaScript' 카테고리의 다른 글
동적 UI 만드는 방법 (0) | 2023.03.26 |
---|---|
자바스크립트를 왜 쓰는가? (0) | 2023.03.26 |
🔖 객체지향5. class를 복사하는 extends / super (1) | 2023.03.02 |
🔖 객체지향4. ES6방식으로 구현하는 상속기능 (class) (0) | 2023.02.28 |
🔖 Object.create()로 구현하는 상속기능 (0) | 2023.02.28 |