모든 코드에 의미를 담겠습니다.
얕은복사 / 깊은복사에 대해서 설명을 할때에 객체로 설명하는 것이 가장 좋겠다. 이전 문서에 설명했던 데이터타입의 불변성/가변성에 대해서 알고 있다면 얕은복사 및 깊은복사에 대해서 조금 더 쉽게 접근할 수 있다.
Javascript에서는 변수또는 객체를 복사할 때 값을 복사하는게아니라 주소를 복사한다.
원시자료(Primitive) 데이터 같은 경우는 변수의 주소가 있고 데이터 값에 대한 부분을 또 다른 주소에 저장을 하기때문에 데이터 자체는 불변해서 불변성을 띄는 것이다.
var a = 10
var b = a;
b = 5;
console.log(a) // 10
console.log(b) // 5
변수의 선언과 할당은 불변성의 법칙에 따라서 그렇게 된다지만 객체같은 경우는 어떨까? 완전히 다르다. 객체같은 경우는 가변성을 띄운다
var obj1 = { c:10, d: 'ddd'};
var obj2 = obj1;
obj2.c = 20
console.log(obj1) // {c:20, d: 'ddd'}
console.log(obj2) // {c:20, d: 'ddd'}
왜 이렇게 변하는 것일까?
자세히 살펴보니 obj2의 c값을 변경했더니 obj1의 c값도 변경되었다. 이유는 간단하다. obj2의 c값을 변경할때 값을 변경한게 아니라 원래 c가 저장되어있던 주소의 값을 변경했기때문에 같이 공유하던 obj1의 값이 같이 변경된 것이다!
좀 더 자세하게 설명해보겠다
obj1이라는 변수명과값은 1에 obj2라는 변수명과 값이 2에 저장이 되어있다.
여기서 값은 또다시 두 데이터값을 저장한 #10이라는 주소를 가르키고 있고 obj2 데이터값이 같기때문에 #10을 가르키고 있는 것이다.
그리고 #10이라는 주소안에는 또다시 c와 값을 저장하는 주소 #100과
#11이라는 주소안에는 d 키값과 값을 저장하는 주소 #101이 생성된것이다.
여기서 obj2.c = 20 이 되면서 #100안의 c값이 변했는데, obj1또한 #100을 가르키고 있었기 때문에 obj 1 & obj2 둘다 변한것이다.
이러한 문제점을 해결하기 위해서 나온 개념이 얕은복사 vs 깊은 복사인것이다.
const obj2 = {...obj1} // spread연산자를 이용하면 obj1의 값만 가져오는 것이기때문에 주소를 건드리지않는다.
const obj2.c = 20
console.log(obj1) // 둘이 다른값을 가져온다는 것을 알 수 있다.
console.log(obj2)
하지만 여기서 생기는 또하나의 문제점이 있다. 만약에 객체안에 또다른 객체가 있다고 하면 어떻게 될까? 결국 객체안의 객체를 또다시 spread문법으로 복사하게되면 주소를 또 그대로 복사하는 경우가 생기기때문에 원래 변수의 값 또한 건들게 된다.
이럴경우에는 JSON stringfy를 써서 해결해야한다.
1. JSON.stringfy(obj1) //child 12을 JSON 객체화 시킨다.
2. JSON.parse(JSON.stringfy(obj1))
3. const obj1 = JSON.parse(JSON.stringfy(obj2))
이렇게 해주면 된다. 데이터 타입에 대해서 조금 더 잘알고 있다면 해당 부분을 쉽게 이해할 수 있을 것 같다.
이렇게 매일 조금씩 javascript문법에대해서 공부하면 좋을 것 같다.