Core Javascript-얕은복사 vs 깊은 복사

kyj2471·2021년 3월 29일
0

코어 자바스크립트란 책을 읽으면서 스스로 정리한 내용입니다
혹시 잘못된 내용이 있으면 수정하겠습니다.

얕은 복사 vs 깊은 복사

복사면 복사지 얕은 복사는 뭐고 깊은 복사는 무엇일까?
우선 얕은 복사는 바로 아래 단계의 값만 복사고 깊은 복사는 내부 모든 값을 하나하나 찾아내어 전부 복사한다는 것이다.
이게 무슨 말일까?
우리는 앞서 데이터 타입에 관한 공부를 하였다.
참조형 데이터는 저장된 프로퍼티를 복사시 그 주솟값을 복사한다.
결론적으로 사본과 원본이 같은 주소를 가리키게 됩니다. 그러면 원본이 바뀌면 사본이 바뀌고 사본이 바뀌면 원본이 바뀌는 문제가 생긴다.
그래서 기본형 데이터는 그대로 복사하면 되지만 참조형은 그내부의 프로퍼티 까지 복사해야한다.

얕은 복사

  • slice복사
  • spread복사
  • assign복사

깊은 복사

  • 재귀적 방법
  • JSON.parse & JSON.stringify

얕은복사

Array.prototype.slice()

공식 문서slice()에 관해 찾아보면 begin부터 end까지 에 대한 얕은 복사본 으로 새로운 배열 객체로 반환한다.
slice()는 원본을 대체하지 않는다. 원본 배열에서 요소의 얕은 복사본을 반환한다... 라고 적혀있다.

const arr = [ 1, 2, 3, 4, 5]
const copyArr = arr.slice();
checker(arr, copyArr) //true
checker(arr, copyArr) //false

하지만 slice()는 중첩 구조 복사를 제대로 수행할 수 없다는 단점이있다.

const arr = [ 1, 2, 3, [4, 5]]
const copyArr = arr.slice();
checker(arr, copyArr) //true
checker(arr, copyArr) //true

위와 같이 중첩된 구조를 변경하면 원본 배열과 복사된 배열이 모두 영향을 받는다.

Spread 복사

앞서 공부한 Symbol.iterator프로퍼티를 이용하여 복사한다.

const arr = [ 1, 2, 3, [4, 5]]
const copyArr = [...arr]
checker(arr, copyArr) //true
copyArr[3].push(7)
console.log(copyArr)//[ 1, 2, 3, [ 4, 5, 7 ] ]
checker(arr, copyArr)//true

Spread역시 중첩된 구조의 배열은 불변성을 지키지 못하며 복사한다.

Object.assign

const arr = [1, 2, [3, 4]];
const copyArr = Object.assign([], arr);
checker(arr, copyArr); //true
copyArr[2].push(5);
checker(arr, copyArr) //true

공식문서에 Object.assign의 deep copy에 관하여 찾아보면 깊은 복사에 대해서, Object.assign() 은 속성의 값을 복사하기때문에 다른 대안을 사용해야합니다. 출처 값이 객체에 대한 참조인 경우, 참조 값만을 복사합니다.Object.assign역시 중첩구조에서의 불변성을 지키지 못한다.

깊은 복사

JSON.parse & JSON.stringify
위에서 봤던 방법들은 결국 중첩 구조를 불변성을 지키며 복사하는 것에 대해 실패하였다.
JSON.stringify 를 활용해 데이터를 문자로 변형시키고
JSON.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

하지만 JSON은 function, arrow function, undefined는 불가하다

profile
[ frontend-developer ]

0개의 댓글