[Javascript] 원시,참조자료형 & 얕은복사,깊은복사

tnsdlznf23·2023년 3월 2일
0

자료형이란?

Javascript에서 자료형(type)이란 값의 종류이다.
크게 원시 자료형(primitive type)참조 자료형(reference type)으로 나눌 수 있다.

원시자료형

number, string, boolean, undefined, null, symbol
6개의 자료형이 원시 자료형이다.

  • 원시 자료형을 변수에 할당하면 메모리 공간에 값 자체가 저장이 된다.
  • 원시자료형을 갖는 변수를 다른 변수에 할당하면 원시 값 자체가 복사된다.
  • 원시 자료형은 변경불가능한 값이다. 한번 생성된 원시자료형은 읽기 전용 값이 된다.
    따라서 string 값의 인덱스를 직접 변경할 수 없다.

원시값은 변경할 수 없다는데 변경이 되네?

변수에 할당된 원시값을 변경하게 되면 메모리 내부에서는 변경된 값을 저장하기 위한 새로운 공간을 확보한 뒤, 그 공간에 변경된 값을 저장하고, 남아있는 기존 값은 사용하지 않으므로 자동으로 메모리에서 삭제합니다. 이런 기능을 가비지 콜렉터(garbage collector)라고 합니다. 그러나 가비지 콜렉터가 어느 시점에 진행되는지는 예측할 수 없습니다.

참조자료형

객체, 배열

  • 참조 자료형을 변수에 할당하면 저장공간(heap)주솟값이 저장된다.
  • 참조 값을 갖는 변수를 다른 변수에 할당하면 주솟값이 복사되어 전달된다.
  • 참조 자료형은 변경이 가능한 값(mutable value)이다.
  • 복사된 변수의 값을 변경하면 기존 변수의 값도 같이 변경이 된다.

얕은 복사

배열 복사

  • slice() : arr.slice()로 배열을 복사할 수 있다.
  • spread syntax : let copiedArr = [...arr]로 배열을 복사할 수 있다.

객체 복사

  • Object.assign() : let copiedObj = Object.assign({}, obj);으로 객체를 복사할 수 있다.
  • spread syntax : let copiedObj = {...obj};로 객체을 복사할 수 있다.

얕은 복사의 한계

  • 참조 자료형 내부에 참조 자료형이 중첩되어 있는 경우, slice(), Object.assign(), spread syntax를 사용해도 참조 자료형 내부에 참조 자료형이 중첩된 구조는 복사할 수 없다. 참조 자료형이 몇 단계로 중첩되어 있던지, 위에서 설명한 방법으로는 한 단계까지만 복사할 수 있다.

깊은 복사

참조 자료형 내부에 중첩되어 있는 모든 참조 자료형을 복사하는 것은 깊은 복사(deep copy)라고 한다. 그러나 JavaScript 내부적으로는 깊은 복사를 수행할 수 있는 방법이 없다. 단, JavaScript의 다른 문법을 응용하면 깊은 복사와 같은 결과물을 만들어 낼 수 있습니다.

1. JSON.stringify()와 JSON.parse()

  • 중첩된 참조 자료형을 JSON.stringify()를 사용하여 문자열의 형태로 변환하고, 반환된 값에 다시 JSON.parse()를 사용하면, 깊은 복사와 같은 결과물을 반환한다.
  • 한계 : 중첩된 참조 자료형 중에 함수가 포함되어 있을 경우 위 방법을 사용하면 함수가 null로 바뀌게 된다.
  • 코드 : const copiedArr = JSON.parse(JSON.stringify(arr));




2. 외부라이브러리 사용

  • 완전한 깊은 복사가 필요하다면 node.js 환경에서 외부 라이브러리인 lodash, 또는 ramda를 설치하면 된다.
const lodash = require('lodash');

const arr = [1, 2, [3, 4]];
const copiedArr = lodash.cloneDeep(arr);

추가 TIL

  • 참조값을 가지는 변수를 복사한 후 복사한 변수에 원시값을 재할당하면 복사만 변수의 값만 변한다.
let x = { foo: 3 };
let y = x;
y = 2;

//결과 x = { foo: 3 } , y = 2
profile
프론트엔드 개발 기록장

0개의 댓글