JavaScript_기본형과 참조형

cho·2023년 7월 19일

📖 자료형의 종류

기본형(Primitive Type)참조형(Reference Type)
Number
String
BooleanObject
Null
Undefined

✏️ 기본형 (Primitive Type)

값이 그대로 할당된다.
변수 = 값

let x = 3;
let y = x;

console.log(x); // 3
console.log(y); // 변수 x가 가지고 있는 3을 복사해서 담는다. 3
y = 5; // 새로운 값을 할당해준다.
console.log(x); // 3
console.log(y); // 5

✏️ 참조형 (Reference Type)

해당 객체를 가리키는 주소값이 할당된다.
변수 = 주소값

let x = {name: 'Codeit'};
let y = x; // x와 같은 주소값이 할당된 것.

console.log(x); // {name: 'Codeit'}
console.log(y); // {name: 'Codeit'}

y.birth = 2017;
console.log(x); // {name: 'Codeit', birth: 2017}
console.log(y); // {name: 'Codeit', birth: 2017}

자바스크립트에서 변수에 객체값을 할당하는 경우 특별하게 동작을 한다. 객체값이 만들어지면 변수에는 그 객체값의 주소가 할당된다.
변수상자와 객체값 상자 사이에 주소라는 길이 열리는 것이다. 때문에 y만 수정을 했지만 x와 y가 서로 같은 객체를 바라보게 됨으로 같은 값을 가지게 된다. 이렇게 주소값을 참조해서 그 객체에 접근하기 때문에 참조형이라고 부르는 것이다.

📚 배열도 참조형

배열도 객체이므로 Reference Type이다.

let x = [1, 2, 3];
let y = x;

console.log(x); // [1, 2, 3]
console.log(y); // [1, 2, 3]

y[2] = 4;
console.log(x); // [1, 2, 4]
console.log(y); // [1, 2, 4]

✏️ 참조형 복사하기 (Reference Type Copy)

let numbers1 = [1, 2, 3]; // 객체의 주소값 할당
let numbers2 = numbers1; // 주소값 복사

numbers2.push(4);

console.log(numbers1); // [1, 2, 3, 4]
console.log(numbers2); // [1, 2, 3, 4]

📚 배열에서

만약 numbers2 배열만 바꾸고 싶다면 문자열 method로 사용했던 slice method를 활용할 수 있다. slice method를 호출할 때 parameter값으로 아무것도 전달하지 않으면 원래 값이 그대로 return되는 것을 활용하여 마치 배열을 복사하는 것과 같은 효과를 낼 수 있다.

let numbers1 = [1, 2, 3]; // 객체의 주소값 할당
let numbers2 = numbers1.slice(); 

numbers2.push(4);

console.log(numbers1); // [1, 2, 3]
console.log(numbers2); // [1, 2, 3, 4]

📚 객체에서

객체에는 slice method가 없으나 Object 객체의 assign method를 활용하면 복사할 수 있다.

let course1 = {
  title: '파이썬 프로그래밍 기초',
  language: 'Python'
};

let course2 = course1;

course2.title = '알고리즘의 정석';

console.log(course1); // {title: "알고리즘의 정석", "Python"}
console.log(course2); // {title: "알고리즘의 정석", "Python"}
let course1 = {
  title: '파이썬 프로그래밍 기초',
  language: 'Python'
};

let course2 = Object.assign({}, course1);

course2.title = '알고리즘의 정석';

console.log(course1); // {title: "파이썬 프로그래밍 기초", "Python"}
console.log(course2); // {title: "알고리즘의 정석", "Python"}

🌟Object.assign이란?

Object.assign을 이용해서 객체를 합치는 것이 가능하다. 또한 합칠 때는 2개의 객체가 같은 프로퍼티를 가지고 있다면 그 값을 덮어쓰기 해주며, 객체의 복제에서도 사용될 수 있다.
https://engineer-mole.tistory.com/151#google_vignette

📚 for...in문으로 객체 복사하기

function cloneObject(object) {
  let temp = {};
  
  for (let key in object) {
    temp[key] = object[key];
  }
  
  return temp;
};

let course1 = {
  title: '파이썬 프로그래밍 기초', 
  language: 'Python'
};

let course2 = cloneObject(course1);
let course3 = cloneObject(course1);

course2.title = '알고리즘의 정석';
course3.title = '객체 지향 프로그래밍';

console.log(course1); // {title: "파이썬 프로그래밍 기초", language: "Python"}
console.log(course2); // {title: "알고리즘의 정석", language: "Python"}
console.log(course3); // {title: "객체 지향 프로그래밍", language: "Python"}

⚠️ 주의할 점
만약 객체안에 배열도 함께 들어가 있다면 그 배열의 주소값이 복사되기 때문에 이러한 결과가 나온다.

function cloneObject(object) {
  let temp = {};
  
  for (let key in object) {
    temp[key] = object[key];
  }
  
  return temp;
};

let course1 = {
  title: '파이썬 프로그래밍 기초', 
  language: 'Python',
  prerequisite: []
};

let course2 = cloneObject(course1);

course2.title = '알고리즘의 정석';
course2.prerequisite.push('파이썬 프로그래밍 기초');

console.log(course1);  // {title: "파이썬 프로그래밍 기초", language: "Python", prerequisite: "파이썬 프로그래밍 기초"}
console.log(course2); // {title: "알고리즘의 정석", language: "Python", prerequisite: "파이썬 프로그래밍 기초"}

이 문제는 배열의 slice method나 object method를 사용해도 동일하게 일어나는 문제이다. 객체나 배열안에 중첩해서 또 다른 객체나 배열이 있는 경우, 복사할 때 또 주소값을 복사할 수 있어 예상치 못한 값을 도출하게 될 가능성이 있음을 기억해야한다.

4개의 댓글

comment-user-thumbnail
2023년 7월 19일

너무 좋은 글이네요. 공유해주셔서 감사합니다.

1개의 답글
comment-user-thumbnail
2023년 7월 22일

정리가 깔끔하네요!

1개의 답글