JavaScript는 두 가지 원시 타입(Primitive Type)
과 참조타입(Reference Type)
이 있다.
원시 타입은 쉽게 말해, 정수, 실수, 문자, 논리 리터럴등의 실제 데이터 값을 저장하는 타입이고,
참조 타입은 객체(Object)의 번지를 참조(주소를 저장)하는 타입으로 메모리 번지 값을 통해 객체를 참조하는 타입이다.
원시형 타입은 복사를 할 때 값 자체를 복사한다.
const number = 1;
const num2 = number;
console.log(num2);
>>> 1
위와 같은 코드에서 num2 는 1이라는 값 자체를 받아온 하나의 정수 데이터 타입이다. 또 값 자체를 받아왔기 때문에 아래와 같이 할당 이후에 number
의 값을 바꿔도 num2
의 값은 바뀌지 않는다.
let number = 1;
const num2 = number;
number = 2;
console.log(num2);
>>> 1
객체와 배열은 참조형 타입이다.
const Person = {
name: "max"
};
const person2 = Person;
console.log(person2);
>>> [object Object] {
name:"max"
}
여기서 Person 매모리에 객체가 저장되고, person2는 메모리에 포인터가 저장된다. 그래서 const person2 = Person;
구문 이후에 Person의 이름을 바꾸고 똑같이 콘솔에 값을 찍어보면 참조형 타입에 대한 이해 없이 바라봤을 때와 다른 결과값을 볼 수 있다.
const Person = {
name: "max"
};
const person2 = Person;
Person.name = "min";
console.log(person2);
>>> [object Object] {
name:"min"
}
분명 값을 넘겨준 이후에 값을 바꾸었지만 값은 똑같이 변했다. 이것이 참조했다고 하는 이유이다. 단지 포인터를 복사해서 새로운 객체가 가르키도록 했기 때문이다. 이를 이해하는 것은 중요하다. 다른 곳에서 같은 객체를 참조하고 있다가 데이터 변경이 일어났을 때 예상치 못한 효과가 발생할 수 있기 때문이다.
그렇다면 이것을 완전히 새로운 객체로 받으려면 어떻게 해야할까?
바로 객체를 만들고 다른 인스턴스의 속성을 전개하면 된다.
const Person = {
name: "max"
};
const Person2 = {
...Person
}
Person.name = "min";
console.log(Person2);
>>> [object Object] {
name:"max"
}
다음과 같이 하면 진짜로 우리가 원하는 객체의 복사가 일어난다.