| 기본형(Primitive Type) | 참조형(Reference Type) |
|---|---|
| Number | |
| String | |
| Boolean | Object |
| Null | |
| Undefined |
값이 그대로 할당된다.
변수 = 값
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
해당 객체를 가리키는 주소값이 할당된다.
변수 = 주소값
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]
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을 이용해서 객체를 합치는 것이 가능하다. 또한 합칠 때는 2개의 객체가 같은 프로퍼티를 가지고 있다면 그 값을 덮어쓰기 해주며, 객체의 복제에서도 사용될 수 있다.
https://engineer-mole.tistory.com/151#google_vignette
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를 사용해도 동일하게 일어나는 문제이다. 객체나 배열안에 중첩해서 또 다른 객체나 배열이 있는 경우, 복사할 때 또 주소값을 복사할 수 있어 예상치 못한 값을 도출하게 될 가능성이 있음을 기억해야한다.
너무 좋은 글이네요. 공유해주셔서 감사합니다.