[코드스테이츠/13DAY] Unit9 - [JavaScript] 핵심 개념과 주요 문법 - 참조자료형

오은비·2023년 3월 2일
0

코드스테이츠

목록 보기
13/18
post-thumbnail

참조 자료형

📚 원시 자료형 VS 참조 자료형

자바스크립트에서 제공하는 7가지 데이터 타입(number, string, boolean, Null, undefined, symbol, object)은 number, string, boolean, null, undefined , symbol 과 같이 고정된 저장 공간을 가진 자료형인 원시 자료형과, 대량의 데이터를 다루기에 적합한 배열객체 등의 참조 자료형으로 구분할 수 있다.

📌 원시 자료형

: 원시 타입의 값, 즉 원시 값은 변경 불가능한 값이다. 읽기 전용 값으로서 변경할 수 없다.
변경 불가능하다는 것은 변수가 아닌 값에 대한 진술이다. "원시 값은 변경 불가능하다"는 말은 원시 값 자체를 변경할 수 없다는 것이지 변수 값을 변경할 수 없다는 것이 아니다.

원시 자료형의 특징
- 변경 불가능한 값, 즉, 읽기 전용이다.
- 어떤 일이 있어도 불변하는 특성 덕분에 데이터의 신뢰성을 보장한다.
- 변수에 할당하면 메모리 공간에 값 자체가 저장 된다.
- 원시 값을 갖는 변수를 다른 변수에 할당하면 원시 값 자체가 복사되어 전달 된다.
- 원시 값을 할당한 변수에 새로운 원시 값을 재할당하면 메모리 공간에 저장되어 있는 재할당 이전의 원시 값이 아니라 새로운 메모리 공간을 확보하고 재할당한 원시 값을 저장한 후, 변수는 새롭게 재할당한 원시 값을 가리킨다. → 이런 특성을 불변성이라고 한다.
- 두 변수의 원시 값은 서로 다른 메모리 공간에 저장된 별개의 값이 되어 어느 한쪽에서 재할당을 통해 값을 변경하더라도 서로 간섭 할 수 없다.

📌 참조 자료형

: 참조(객체) 타입의 값, 즉 객체는 변경 가능한 값이다. 참조 값은 생성된 객체가 저장된 메모리 공간의 주소, 그 자체다.

참조 자료형의 특징
- 변수에 할당하면 주솟값이 저장 된다.
- 참조 값을 갖는 변수를 다른 변수에 할당하면 주솟값이 복사되어 전달된다.
- 참조 자료형은 변경이 가능한 값이다.
- 객체를 할당한 변수는 재할당 없이 객체를 직접 변경할 수 있다.
- 여러 개의 식별자가 하나의 객체를 공유할 수 있다는 단점을 가진다.


📚 자료형의 복사

  • 원시 자료형의 복사 : 값 자체의 복사
    → 원본과 복사본 중 하나를 변경해도 다른 하나에 영향을 미치지 않는다.

  • 참조 자료형의 복사 : 메모리에 저장되어 있는 주소가 복사
    → 원본과 복사본이 같은 주소를 참조한다.
    → 참조 자료형의 주솟값을 복사한 변수에 요소를 추가하면 같은 주소를 참조하고 있는 원본에도 영향을 미친다.
    참조 자료형이 저장된 변수를 다른 변수에 할당할 경우, 두 변수는 같은 주소를 참조하고 있을 뿐 값 자체가 복사 되었다고 볼 수 없다.

얕은 복사는 객체에 중첩되어 있는 객체의 경우 참조 값을 복사하고, 깊은 복사는 객체에 중첩되어 있는 객체까지 모두 복사해서 원시 값처럼 완전히 복사본을 만든다는 차이가 있다.
→ 원시 값을 할당한 변수를 다른 변수에 할당하는 것을 깊은 복사, 객체를 할당한 변수를 다른 변수에 할당하는 것을 얕은 복사라고도 부른다.


📚 배열 복사하기

slice()

: 배열 내장 메서드. 주소가 다르기 때문에 복사한 배열에 요소를 추가해도 원본 배열에는 추가 되지 않는다.

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

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

spread syntax (ES6)

: ES6에서 새롭게 추가된 문법으로, 배열을 펼칠 수 있다. 배열이 할당 된 변수 명 앞에 ...을 붙여주면 된다.

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

  copiedArr.push(4);
  console.log(copiedArr); // [0, 1, 2, 3, 4]
  console.log(arr); // [0, 1, 2, 3]
// 각각 다른 주소를 참조한다.



📚 객체 복사하기

Object.assign()

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

console.log(copiedObj) // { firstName: "ori", lastName: "nuguri" }
console.log(obj === copiedObj) // false

spread syntax

let obj = { firstName: "ori", lastName: "nuguri" };
let copiedObj = {...obj};

console.log(copiedObj) // { firstName: "ori", lastName: "nuguri" }
console.log(obj === copiedObj) // false

예외

: 참조자료형 내부에 참조 자료형이 중첩되어있는 경우 slice(), Object.assign(), spread syntax를 사용해도 참조 자료형 내부에 참조 자료형이 중첩된 구조는 한 단계까지만 복사한다.
이것을 얕은 복사(shallow copy)라고 한다.



📚 얕은 복사 vs 깊은 복사

얕은 복사

: 참조 자료형 내부에 참조 자료형이 중첩된 구조를 복사할 때 한 단계까지만 복사되는 것을 말한다.

깊은 복사

: 참조 자료형 내부에 중첩되어 있는 모든 참조 자료형을 복사하는 것을 깊은 복사(deep copy)라고 한다.
JS 내부적으로는 깊은 복사를 수행할 수 있는 방법은 없으며, 다른 문법을 응용하여 같은 결과물을 만들어 낼 순 있다.

  • JSON.stringify() : 참조자료형 → 문자열 형태로 변환하여 반환
  • JSON.parse() : 문자열 형태 → 객체로 변환하여 반환
const arr = [1, 2, [3, 4]];
const copiedArr = JSON.parse(JSON.stringify(arr));

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

단, 함수가 포함되어 있을 경우 함수는 null로 바뀌게 되기 때문에 완전한 깊은 복사 방법이라 보기 어렵다.

외부 라이브러리 사용

node.js환경에서 외부라이브러리인 lodash 또는 ramda를 설치하면 된다.

ladash 예시

const lodash = require('lodash');

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

console.log(arr); // [1, 2, [3, 4]]
console.log(copiedArr); // [1, 2, [3, 4]]
console.log(arr === copiedArr) // false
console.log(arr[2] === copiedArr[2]) // false
profile
드림오구

2개의 댓글

comment-user-thumbnail
2023년 3월 3일

const namazuo = {'i', 'love', 'namazuo'};
const cute = namazuo.slice(1, -1);
console.log(you ${cute[0]} ${cute[1]});
// you love namazuo

1개의 답글