코딩/코드스테이츠 45기(FE)

블로깅 챌린지 4주차 - [JS] 자료형과 복사

2워노 2023. 5. 1. 13:40

1. 자료형

⚡️ 데이터의 두가지 타입

  • 데이터의 타입은 원시 자료형(primitive type)과 참조 자료형(reference type)이 있다.
  • 원시 자료형이 할당 될때에는 변수에 값(value) 자체가 담긴다.
  • 참조 자료형이 할당 될때에는 보관함의 주소(reference)가 담긴다.

 

⚡️원시 자료형(Primitive type)

  • 원시자료형이란 하나의 보관함에 하나의 데이터만을 담고 변수의 이름으로 저장하는 것을 말한다.
  • 원시 자료형에는  6가지의 타입이 있다.
  • string, number, boolean, undefined, symbol, bigint, null
    • string : 'WONHO'
    • number : 19930215
    • boolean : true / false
    • undefined : 변수가 정의되지 않았거나 값이 없는 경우
    • bigint : 9007199254740991n
    • null : 의도적으로 비어있는 공간을 표시하기 위함
  • 값이 변하지 않는 불변성(immutable)을 갖고 있다.
  • 따라서, 재할당 시 기존 값이 변하는 것처럼 보일지라도, 사실 새로운 메모리에 재할당한 값이 저장되고 변수가 가르키는 메모리가 달졌을 뿐인 것이다.
  • (데이터 복사가 일어날 때 메모리 공간을 새로 확보하여 독립적인 값을 저장)

 

⚡️ 참조 자료형(Reference type)

  • 자바스크립트에서는 원시 자료형이 아닌 모든것을 참조 자료형이라고 한다.
  • 배열과 객체, 함수가 대표적인 참조 자료형이다.
  • 참조 자료형은 변수에 할당할 때 값을 저장하는 것이 아닌 주소를 저장한다.
  • 변수는 주소를 저장하고, 주소는 특별한 동적인 데이터 보관함(Heap)에 보관된다.
  • 값을 재할당 할 경우 해당 주소를 참조한 모든 값이 영향을 받는다. (= 즉, 값이 공유되는 특성을 지닌다.)

 

❗️ 요약

원시 자료형(Primitive type) 참조 자료형(Reference type)
고정된 저장공간 동적인 저장공간
하나의 데이터만 담음 여러개의 데이터를 담음
할당시 '값'만 복사
(다른 변수에 복사 후 변경해서, 원본은 변경 X)
( immutable )
할당시 '주소'까지 복사
(다른 변수에 복사 후 변경시, 기존 변수까지 변경됨)
( mutable )
ex) string, number, boolean, undefined, symbol, bigint, null ex) 배열, 객체 , 함수 등

 

 

2. 얕은 복사와 깊은 복사

⚡️ 얕은 복사(shallow copy)란?

  • 참조 타입 데이터가 저장한 '메모리 주소 값'을 복사한 것을 의미한다.
  • 얕은 복사는 참조 복사객체 복사로 나눌 수 있다.

 

❗️ 얕은 복사 _ 참조 복사

// 얕은복사_참조복사 예시

let obj1 = { a: 1, b: 2, c: 3};
let obj2 = obj1;
console.log( obj1 === obj2 ); // true
  • 위의 예시와 같이 객체를 직접 대입하는 경우 참조에 의한 할당이 이루어 지기 때문에, 둘은 같은 주소를 가지고 있다.
  • 이것이 얕은 복사(참조 복사)이다.
let obj1 = { a: 1, b: 2, c: 3};
let obj2 = obj1;
console.log( obj1 === obj2 ); // true

obj2.a = 1000;

console.log( obj1.a ); // 1000
  • 위 두 객체는 같은 주소(데이터)를 가지고 있다.
  • 따라서, obj2의 property를 수정하고, obj1을 출력해도 obj2값과 동일하다.

 

❗️ 얕은 복사 _ 객체 복사

  • 방법1.  ...(spread) 연산자를 통한 복사
let obj1 = { a: 1, b: 2, c: [3, 4]};
const obj2 = { ...obj1 };;
console.log( obj1 === obj2 ); // false

obj2.a = 1000;

console.log( obj1.a ); // 1
console.log( obj1.c === obj2.c ) // true

obj2.c[0] = 33;

console.log( obj1.c[0] ) = 33; // 객체 내 배열의 값은 같은 주소를 참조하기 때문에
			     // obj2.c[0]을 변경하면 obj1.c[0]의 값도 변경됨
  • ...(spread) 연산자를 통해 obj1의 속성을 복사하여 obj2에 할당하였다.
  • obj1과 obj2는 다른 주소를 갖게 되었으나, 객체 속의 배열 c: [3, 4]는 동일한 주소값을 공유한다

 

  • 방법2. Object.assign() 메서드를 통한 복사
let obj1 = { a: 1, b: 2, c: [3, 4]};
let obj2 = Object.assign({}, obj1)

obj2.a = 1000;

console.log( obj1 === obj2 ) /// false
console.log( obj1.a ); // 1
console.log( obj1.c === obj2.c ) // true

obj2.c[0] = 33;

console.log( obj1.c[0] ) = 33; // 객체 내 배열의 값은 같은 주소를 참조하기 때문에
			     // obj2.c[0]을 변경하면 obj1.c[0]의 값도 변경됨
  • Object.assign() 메서드를 이용하여 첫번째 인자로 빈 객체를, 두번쨰 인자로 obj1을 넣어 obj2에 할당 하였다.
  • obj1과 obj2는 다른 주소를 갖게 되었으나, 객체 속의 객체 c: [3, 4]는 동일한 주소값을 공유한다

 

 

⚡️ 깊은 복사(deep copy)란?

  • 새로운 메모리 공간을 확보하여 완전히 복사하는 것을 의미한다.
  • 얕은 복사 처럼 주소를 복사하여 공유하는 것이 아닌, 아예 새로운 객체안 속성만 복사하는 것이다.

 

⚡️ 완벽한 Deep copy 방법

  • 위 2가지 방법 (spead 연산자와 Object.assign 메서드) 모두 Shallow copy 이다.
  • JSON.parse()와 JSON.stringify()함수를 사용하면 Deep copy 구현이 가능하다.
  • 하지만, 위의 방법도 객체 내부에 함수가 포함된다면 함수의 값이 null로 바뀌게 되어 사용할 수 없다.
  • 따라서 lodash, ramda, 및 rdfc 등의 외부 라이브러리를 이용하여야 한다 (추후 업로드 예정)

 

 

Reference