JavaScript 공부 - 원시자료형과 참조자료형

0

JavaScript

목록 보기
6/11
post-thumbnail

JavaScript의 자료형은 '원시자료형'과 '참조자료형'으로 구분된다!

원시자료형 : number, string, boolean, undefined, null, symbol (흔히 아는 자료형 타입)
참조자료형 : 위 6개의 원시자료형을 제외한 나머지 자료형 (배열, 객체, 함수 등)

이 둘은 생각보다 큰 차이가 존재한다

원시자료형

  1. 값을 변수에 할당하면 메모리 공간에 값 자체가 저장된다.
  2. 해당 원시값 변수를 다른 변수에 할당하면 원시값이 그대로 복사되어 전달된다.
  3. 변경이 불가능한 값이다.

참조자료형

  1. 변수에 할당하면 메모리 공간에 해당 값의 주솟값이 저장된다.
  2. 해당 참조값 변수를 다른 변수에 할당하면 해당 값의 주소값이 복사되어 전달된다.
  3. 변경이 가능한 값이다.
let num = 10;
let copynum = num;
let arr = [1,2,3];
let copyarr = arr;

이러한 방식으로 원시자료형과 참조자료형을 생성한 뒤 복사를 했다고 가정한다면, copynum에도 10이 저장되고, copyarr에도 [1,2,3]이 저장되긴 한다.
하지만 copynum은 num의 값만 복사해온 것이기에 여기서 만약 copynum의 값을 변경한다 해도 num의 값에 영향을 미치지 않는다.
이와 달리 copyarr은 arr의 값인 [1,2,3]을 가져온 것이 아니라 [1,2,3]의 주소값을 가져온 것이기에 같은 주소를 참조하고 있다. 이로 인해 copyarr의 값을 변경할 경우, arr 또한 copyarr과 같은 주소의 배열을 참조하고 있기에 arr 또한 값이 같이 변경되게 된다.

copynum = 20;
console.log(copynum);   //20
console.log(num);   //10;

copyarr.push(4);
console.log(copyarr);   //[1,2,3,4]
console.log(arr);   //[1,2,3,4]

하지만 배열과 객체와 같은 참조자료형을 주소값 복사가 아닌 원시자료형처럼 값 자체를 복사하여 따로 편집하고 싶은 경우가 한번쯤은 생기기 마련이다. 이런 경우 대표적으로 사용하는 것이 slice()이다.
배열의 경우 내장 메서드인 slice를 가지고 있는데, 이를 사용하면 원본 배열을 그대로 복사하면서, 다른 주소값을 참조하게 만들 수 있다.

let arr=[1,2,3];
let copied=arr.slice();
console.log(copied);  //[1,2,3]
console.log(copied === arr)   //false  (주소값이 다르기 때문에)

이 경우 copied 배열을 편집하더라도 원본 배열인 arr에 영향을 미치지 않는다.
slice 메서드 말고도 spread syntax를 이용하여도 복사된 배열을 생성할 수 있다.

let arr=[1,2,3];
let copied=[...arr];    //원본 배열 변수 앞에 ...을 붙이면 된다.
console.log(copied);  //[1,2,3]
console.log(copied === arr)   //false  (주소값이 다르기 때문에)

어찌보면 slice보다 더 간단하다고 볼 수 있다. 추가로 spread syntax는 배열 뿐만 아니라 객체에서도 사용이 가능하다!

이렇게 주소값이 바뀌면서 두 자료형을 비교하면 False가 나오게끔 하였다. 근데 여기서 신기한 점은 위 arr의 첫번째 요소와 copied의 첫번째 요소를 꺼내와서 비교하면 True가 나온다는 점이다.

console.log(arr[0] === copied[0]);   //true

순수 배열의 구조만 복사한다고 볼 수 있다. 이러한 복사를 얕은 복사 라고 한다.
얕은 복사와 달리 내부에 있는 모든 자료형을 복사하는 깊은 복사도 존재하긴 하는데, JS 내에 깊은 복사를 수행하는 기능은 존재하진 않다고 한다. 뭐 JSON.stringify()와 JSON.parse() 문법을 이용하여 문자열 형태의 객체로 저장한다면 가능하기도 하지만, 이 또한 완벽한 깊은 복사라 하기도 힘들다. 완벽한 깊은 복사를 실행하기 위해서는 현재로서는 Node.js 환경에서 외부 라이브러리(lodash, ramda)를 이용해야만 실행이 가능하다..!

0개의 댓글