바로 이전 글에서 JS에서 불변성에 대한 글을 남겼고 이번 글은 참조형 데이터가 불변성을 유지할 수 있는 방법 2가지를 알아본다.
얕은 복사란 한 단계까지만 복사하는 것을 의미하며 객체 안에 객체가 담겨 있는 객체의 경우 참조 값을 복사한다.
얕은 복사의 방법으로는 우리가 잘 아는 스프레드 연산자를 사용한다.
const 100 = { name: { first: "gwanghyun", last: "Baek" } };
const shallowCopied100 = {...100};
console.log(shallowCopied100 === 100); //false
console.log(shallowCopied100.name.first === 100.name.first); //true
console.log("재할당 전 원본", 100.name.first); //gwanghyun
console.log("재할당 전 복사본", shallowCopied100.first); //gwanghyun
shallowCopied100.name.first = "pizza";
console.log(shallowCopied100 === 100); //false
console.log(shallowCopied100.name.first === 100.name.first); //true
console.log("재할당 후 원본", 100.name.first); //bumsoo
console.log("재할당 후 복사본", shallowCopied100.name.first); //pizza
왜 false가 출력이 될까?
스프레드 연산자를 사용해서 얕은 복사를 하게되면 서로 다른 메모리 주소값을 가지게 된다.
console.log(shallowCopied100 === 100)
//false 결과를 가져오는 이유는 복사를 했기 때문에 두개는 서로 다른 메모리 주소값을 가진다.
얕은 복사는 다른 메모리에 저장되어 원본 사본이 있는데 재할당을 shallowCopied100.name
에만 했는데 왜 100.name
도 수정된 값 pizza가 출력되나요?
100과 shallowCopied100의 메모리 주소는 다르지만 동일한 참조 값을 갖습니다. 다시 말해 원본과 복사본이 모두 동일한 객체를 가르킨다.
즉, 100에는 참조값인 객체 데이터가 저장된 메모리 주소가 할당되어 있고 같은 주소가 shallowCopied100에도 동일하게 할당되어 있다.
두개의 식별자가 하나의 객체를 공유하는 상황이다.
따라서 원본 또는 사본 중 어느 한쪽에서 객체를 변경하면 서로 영향을 주고 받는다!!.
그럼 중첩된 객체를 복사하고 따로 값을 할당하고 싶을 때는 어떻게 하면 될까요?
이럴땐 깊은복사!
깊은 복사가 된 객체는 객체 안에 객체가 있을 경우에도 원본과의 참조가 완전히 끊어진 객체를 말한다.
깊은 복사를 할 수 있는 방법으로는 JSON.parse && JSON.stringify와 재귀함수도 있지만 쉽지않다. Lodash 라이브러리 쓰자
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); // falseconsole.log(object.number.one === copy.number.one); // falseconsole.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 ] ] }
출처: https://bbangson.tistory.com/78 [뺑슨 개발 블로그:티스토리]