이 글은 Core Javascript를 읽고 내용을 정리하였습니다. 2회독 하였지만 잘못된 내용의 지적을 감사히 받겠습니다.
불변 객체는 프레임워크에서 뿐만 아니라 함수형 프로그래밍, 디자인 패턴 등에서도 매주 중요한 기초가 되는 개념이다. 객체를 복사하는 방법은 간단하게 이 법칙을 지켜줄 수 있기 때문에 흔히 사용되는 방법이다. 객체를 복사하는 방법은 다양하게 있지만 복사되는 성질이 각각 다르기 때문에 복사하는 방법에 대해 정리를 해봤다.
원시형 데이터는 다른 메모리를 할당하기에 복사를 했을 경우 서로 영향을 받지 않는다. 하지만 참조형 데이터일 경우 같은 레퍼런스를 바라보고 있기 때문에 서로 영향을 끼치게 된다.
const arr = [1, 2, 3];
const copied = arr.slice();
checker(arr, copied); // true
copied.push(4);
checker(arr, copied); // false
원본배열과 복사된 배열을 서로 영향을 주지 않게 된다. 하지만 중첩구조의 복사는 서로 영향을 주어 불변성을 지키지 못한다.
Symbol.iterator
프로퍼티를 이용하여 순환하며 복사하는 방법const arr = [1, 2, [3, 4]];
const copied = [ ...arr ];
checker(arr, copied); // true
copied[2].push(5);
checker(arr, copied); // true
Spread 방법 역시 중첩된 구조의 배열은 불변성을 지키며 복사하지 못한다.
const arr = [1, 2, [3, 4]];
const copied = Object.assign([], arr);
checker(arr, copied); // true
copied[2].push(5);
checker(arr, copied); // true
역시 중첩구조의 불변성은 지키지 못한다.
주인공인 격
stringify
: 데이터를 문자로 변형
parse
: 문자를 객체로 변형
을 통해 깊은 복사가 가능하다.
const arr = [1, 2, [3, 4]];
const copied = JSON.parse(JSON.stringify(arr));
checker(arr, copied); // true
copied[2].push(5);
checker(arr, copied); // false
객체를 순환을 통해 옮겨담는것이 아니라 문자열로 변형하여 다시 해석해 객체로 변경하는 과정에서 문자열이 string이고, string은 원시형 데이터 타입이기 때문에 불변성을 지키는 복사가 가능하다.
추가로, JSON객체의 명세는 Object, Arr, Num, str, true, false, null, 만 가능하다(함수, 화살표함수, undefined 불가)
또한 라이브러리를 사용하면 쉽게 깊은 복사가 가능한데,
Lodash 나 Ramda같은 라이브러리를 통해 쉽게 가능하다. 이 라이브러리의 내부를 보게 되면 모든 경우의 수를 예외처리를 통해 깊은 복사를 수행하게 만들어 놨기 때문에 결국에는 우리가 하는 복사를 좀 더 편리하게 해주는 라이브러리!