얕은 복사와 깊은 복사

H·2023년 10월 19일
0

경남 ABC Frontend

목록 보기
8/14

원시 자료형과 참조 자료형

number, string, boolean, null, undefined 과 같은 자료형은 고정된 저장 공간을 차지 : 원시 자료형
대량의 데이터를 다루기에 적합한 배열과 객체 등의 자료형 (array, object, function): 참조 자료형

원시 자료형의 특징

  1. 메모리 공간에 값 자체가 저장된다.
  2. 다른 변수에 할당하면 값 자체가 복사되어 전달된다.
  3. 변경 불가능한 값이다. 한 번 생성된 원시 자료형은 읽기 전용 값이다.

원시 자료형 : 변수에 다른 값을 재할당해도 원시 값 자체가 변경된 것이 아니라 새로운 원시 값을 저장하기 위한 새로운 공간을 확보한 뒤, 그 공간에 num이라는 이름을 붙이고 30을 저장
남아있는 예전값은 가비지 콜렉터로 자동으로 메모리에서 삭제 그러나 어느 시점에 가비지 콜렉터가 진행되는지는 예측 불가
문자열은 원시 자료형이지만 배열처럼 인덱스로 각 문자에 접근이 가능,
하지만 원시 자료형이기에 인덱스에 다른 문자 할당하여 값 변경 불가

참조 자료형의 특징

  1. 메모리 공간에 주소값이 저장된다.
  2. 다른 변수에 할당하면 주소값이 복사되어 전달된다.
  3. 변경이 가능한 값이다.

Javascript는 특별한 저장 공간(힙)에 참조 자료형을 저장한 후, 그 저장공간을 참조할 수 있는 주소값을 변수에 저장한다.

참조 자료형이 할당된 변수를 다른 변수에 할당하면, 이 두 변수는 같은 주소를 가리킨다.
참조 자료형은 원본을 변경하면 복사본도 영향을 받는다. (같은 주소를 참조하고 있기 때문)

배열 복사하기

배열을 복사하는 방법은 크게 두 가지 방법
배열 내장 메서드인 slice() 사용하는 방법과 ES6에서 도입된 spread 문법 사용하는 방법

slice()

let arr = [0,1,2,3];
let copiedArr = arr.slice();
console.log(copiedArr); // [0,1,2,3]
console.log(arr === copiedArr); // false;

새롭게 생성된 배열은 원본 배열과 같은 요소를 갖지만 참조하는 주소는 다르다.

spread syntax

배열을 펼치는 방법은 배열이 할당된 변수명 앞에 ...을 붙여주면 된다.

let arr = [0,1,2,3];
let copiedArr = [...arr];
console.log(copiedArr); // [0,1,2,3]
console.log(arr === copiedArr); // false

객체 복사하기

Object.assign

let obj = { firstName: "coding", lastName: "kim" };
let copiedObj = Object.assign({}, obj);

spread syntax

let obj = { firstName: "coding", lastName: "kim" };
let copiedObj = {...obj};

그러나 참조 자료형 내부에 참조 자료형이 중첩되어 있는 경우, slice(), Object.assign(). spread syntax를 사용해도 참조 자료형 내부에 참조 자료형이 중첩된 구조는 복사 불가
내부에 중첩되어 있는 참조 자료형은 같은 주솟값 참조
중첩된 구조 중 한 단계까지만 복사 : 얕은 복사

깊은 복사

중첩되어 있는 모든 참조 자료형을 복사하는 것
그러나 Javascript 내부적으로는 깊은 복사 수행 방법 x
Javascript의 다른 문법 응용하면 깊은 복사와 같은 결과물 만들 수 있다.

JSON.stringfy()와 JSON.parse()

JSON.stringfy()는 참조 자료형을 문자열 형태로 반환하고, JSON.parse()는 문자열의 형태를 객체로 변환하여 반환
먼저 JSON.stringfy() 사용하고 JSON.parse() 사용하기 : 깊은 복사와 같은 결과물
그러나 함수가 포함되어 있을 경우 함수가 null로 바뀌게 된다. -> 완전한 깊은 복사 방법 x

외부 라이브러리 사용

완전한 깊은 복사를 사용해야 한다면 node.js 환경에서 외부 라이브러리인 lodash, ramda 설치

const lodash = require('lodash');
const copiedArr = lodash.cloneDeep(arr);
profile
나아가기

0개의 댓글