[JS] 얕은 복사 vs 깊은 복사

yooni·2022년 1월 22일
0
post-thumbnail

1. 원시값과 객체

변수 : 값을 담고 있는 메모리 공간 자체 또는 그 메모리 공간의 주소를 가리키는 식별자

1-1. 원시값 (primitive)

: String, Number, Boolean, undefined, Symbol, BigInt
  • 원시값은 변하지 않는다. 재할당이 될 뿐이며, 재할당은 새 메모리 공간을 확보하여 값을 저장한 후 변수가 참조하던 메모리 주소를 변경하는 것이다.
  • 원시값의 복사 : 값을 그대로 복사하지만, 별개의 메모리 공간을 가리킨다.

1-2. 객체 (object)

  • 객체는 크기가 일정하지 않고, 메모리 공간도 많이 차지해 할당할 때마다 생성하지 않고 주소값을 참조하여 사용한다.

2. 객체의 복사

2-1. 얕은 복사 (Shallow copy)

새 객체를 생성하는 복사 방법으로 복사된 객체 자체는 원본 객체와 다른 것이지만 내부의 중첩된 객체는 같은 메모리 주소 값을 가져 같은 값을 참조(공유) 한다. 즉 현재의 depth 보다 더 깊은 depth에서는 깊은 복사가 되지 않는 얕은 복사이다.

  • Object.assign() : 빈 오브젝트의 원본 오브젝트를 병합한 새로운 오브젝트를 반환
const originObj = { a: { b: 1 } };
const copiedObj = Object.assign({}, originObj);

originObj === copiedObj // false
originObj.a === copiedObj.a // true
  • Spread Operation (전개연산자)
const originObj = { a: { b: 1 } };
const copiedObj = {...originObj};

originObj === copiedObj // false
originObj.a === copiedObj.a // true

❓ 그럼 아예 직접적으로 할당해버리는 것은?
- 얕은 복사보다도 얕은(?) 방법이다. 아예 같은 객체를 공유한다.

const originObj = { a: 'apple' };
const copiedObj = originObj
originObj === copiedObj // ture (현 depth에서부터 true)

2-2. 깊은 복사(Deep copy)를 하기 위해서는?

  • JSON.stringify, JSON.parse
    • JSON.stringify 함수를 통해 오브젝트 전체를 문자열로 변환 후 다시 JSON.parse 함수를 이용해 문자열을 오브젝트 형태로 변환하는 방법. 문자열로 변환하는 순간 참조값이 끊겨 새로운 오브젝트가 만들어진다.
    • 이 방법은 리소스를 많이 잡아먹어 느리고 성능이 좋지 않다.
    • 객체가 function일 경우 undefined로 처리한다.
    const originObj = {
    	a: 1,
    	b: {
    		name: 'yooni',
    		gender: 'female'
    		}
    };
    
    const copiedObj = JSON.parse(JSON.stringify(originObj));
    originObj === copiedObj // false
  • cloneDeep 라이브러리 사용
    • 직접적으로 할당하는 방식으로 복사해주어도, 메모리를 새로 할당해 별개의 오브젝트가 된다.
import cloneDeep from lodash/cloneDeep;

const copiedObj = originObj;
copiedObj === originObj // false
  • 이외에도 재귀함수를 구현하는 방법이 있지만 매우 복잡하다.(고 한다.)
profile
멋쟁이 코린이

0개의 댓글