원시 자료형과 참조 자료형

hyxoo·2023년 3월 2일
0

코드스테이츠

목록 보기
11/37
post-thumbnail

📝 [Section1_Unit9] JavaScript 핵심 개념과 주요 문법

📌 원시 자료형 (primitive type)

🔍 JavaScript에서 원시 값(primitive, 또는 원시 자료형)이란 객체가 아니면서 메서드도 가지지 않는 데이터입니다. 원시 값에는 7종류, string, number (en-US), bigint (en-US), boolean, undefined, symbol, 그리고 null이 존재합니다.

🔍 모든 원시 값은 불변하여 변형할 수 없습니다. 원시 값 자체와, 원시값을 할당한 변수를 혼동하지 않는 것이 중요합니다. 변수는 새로운 값을 다시 할당할 수 있지만, 이미 생성한 원시 값은 객체, 배열, 함수와는 달리 변형할 수 없습니다.

✔️ 원시 자료형의 특징

  • 메모리 공간 자체에 값이 저장된다.
  • 원시 자료형은 변경이 불가능하다. 즉, 한 번 생성된 원시 자료형은 읽기 전용(read only) 값이다.
  • 원시 값을 갖는 변수를 다른 변수에 할당하면 값 자체가 복사되어 전달된다.
let a = "a_value";
let b = "b_value";
let a_copy = a;

📌 참조 자료형 (reference type)

🔍 JavaScript에서의 객체속성의 컬렉션으로 볼 수 있습니다. 객체 리터럴 구문을 사용해 제한적으로 속성을 초기화할 수의 있고, 그 후에 속성을 추가하거나 제거할 수도 있습니다.

원시 자료형을 제외한 나머지는 참조 자료형이며, array, object, function 이 모두 포함된다.

✔️ 참조 자료형의 특징

  • 변수에 할당하면 메모리 공간에 값 자체가 아닌 주솟값이 저장된다.
  • 참조 자료형은 변경이 가능한 값(mutable value)이다.
  • 참조 값을 갖는 변수를 다른 변수에 할당하면 주솟값이 복사되어 전달된다.
let arrayA = [0,1,2,3];
let arrayB = ["가", "나", "다"];
let copyA = arrayA;


📌 참조 자료형 복사하기

✔️ 배열의 복사

  • slice() : 배열 내장 메서드인 slice()를 이용하면 배열의 요소들을 그대로 복사하지만, 참조하는 주소값이 다르므로 다른 객체로 판별된다. 따라서 복사한 배열을 수정해도 원본 배열은 수정되지 않는다.
let fruit = ["🍎", "🍊", "🍋", "🥝"];
let copyFruit = fruit.slice();
console.log(copyFruit); // ["🍎", "🍊", "🍋", "🥝"]
console.log(fruit === copyFruit); // false
  • spread syntax : spread syntax는 ES6에서 새롭게 추가된 문법이며 배열 안의 값을 펼쳐준다. 배열 이름 앞에 ...을 붙여 사용한다.
let arr = [0, 1, 2, 3];
console.log(...arr); // 0 1 2 3
let copyArr = [...arr];
console.log(copyArr); // [0, 1, 2, 3]
console.log(arr === copyArr); // false

✔️ 객체의 복사

  • Object.assign() : 객체를 복사할 때 쓰이는 메서드이다.

🔍 Object.assign() 메서드는 출처 객체의 '열거 가능한 자체 속성'만 목표 객체로 복사합니다. (...) 그러므로 Object.assign()은 속성을 단순히 복사하거나 새로 정의하는 것이 아니라, 할당(assign)하는 것입니다.

let obj = { name: "hyesoo", city: "suwon" };
let copiedObj = Object.assign({}, obj);
console.log(copiedObj) // { name: "hyesoo", city: "suwon" }
console.log(obj === copiedObj) // false
  • spread syntax : 객체를 복사할 때에도 spread syntax를 사용할 수 있다. 사용법은 배열과 같다.
let obj = { name: "hyesoo", city: "suwon" };
let copiedObj = {...obj};

console.log(copiedObj) // { name: "hyesoo", city: "suwon" }
console.log(obj === copiedObj) // false

❗️ 예외 사항

참조 자료형 내부에 참조 자료형이 중첩되어 있는 경우에는 slice(), spread syntax, Object.assign()를 사용하면 중첩된 구조 중 한 단계까지만 복사, 즉 얕은 복사(shallow copy)가 된다.

따라서 큰 객체 'users'와 'copiedUsers'를 비교했을 때는 false가 반환되지만, 'users[0]'과 'copiedUsers[0]'을 비교하면 같은 주솟값을 가진 객체를 가르키고 있기 때문에 true가 반환된다.

let users = [
	{
		name: "hyesoo",
		city: "suwon"
	},
	{
		name: "smith",
		city: "newyork"
	},
];

let copiedUsers = users.slice();
console.log(users === copiedUsers); // false
console.log(users[0] === copiedUsers[0]); // true

✔️ 깊은 복사(deep copy)

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

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

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

하지만 중첩된 참조 자료형 중에 함수가 포함되어 있을 경우 위 방법을 사용하면 함수가 null로 바뀌게 된다. 따라서 완전한 깊은 복사를 반드시 해야 한다면, 외부 라이브러리를 사용해야 한다.

profile
hello world!

0개의 댓글