https://developer.mozilla.org/ko/docs/Web/JavaScript/Data_structures
우선 JS의 첫 번째 개념은 참조형과 기본형 데이터 타입으로
기본형 데이터 타입의 변수를 다른 변수에 할당하게 되면, 값 자체가 복사되어 기존 변수의 값이 변경되어도 변경 전 값을 복사한 변수에는 영향을 주지 않는다.
그러나 참조형 데이터 타입의 변수를 다른 변수에 할당하게되면, 기존 변수의 값이 아닌 이를 가리키는 포인터를 할당하기 때문에, 기존 변수의 값이 변경되면 다른 변수의 값도 따라 변경된다.
객체와 원시 데이터(문자열, 숫자, 부울 등)의 근본적인 차이점 중 하나는 객체가 “참조에 의해” 저장되고 복사되는 반면, 원시 데이터는 항상 “전체 값으로” 복사가 된다는 것입니다.
https://javascript.info/object-copy
참고로 여기서 말하는 데이터 타입은 원시값과 객체의 관계가 아닙니다 !
원시형 데이터 타입은 재할당 하거나 변수를 다른 변수에 저장할 때마다 값을 복사함.
let number = 1;
let num2 = number; // 값이 복사됨
number = 11;
console.log(num2) // 1이 출력된다.
객체나 배열은 값을 복사하는 것이 아닌 선언된 변수의 메모리 주소를 카리키는 포인터의 참조를 저장한다.
객체나 배열을 일반적인 할당을 통해 참조하게 되면, 원치 않는 객체와 배열의 조작이 발생할 수 있기 때문에 간단한 복사의 경우 스프레드 연산자를 사용한다.
다음은 person
객체를 복사한 nextPerson
을 출력한 예시와
스프레드 연산자를 통해 person
객체를 복사한 nextPerson
의 출력 예시
const person = {
name:"choi"
};
const nextPerson = person; // person 객체를 참조하게 됨
person.name = "park";
console.log(nextPerson) // name : "choi"가 아닌 name : "park"으로 출력된다.
const person = {
name:"choi"
};
const nextPerson = { // person 객체를 참조하는 것이 아닌 내용이 복사됨
...person
}
person.name = "park";
console.log(nextPerson) // 복사된 값 name: "choi"가 출력된다.
스프레드 연산자를 통해 nextPerson
에는 person
의 속성들이 나열되어 할당되며, 이는 person
의 내용 자체가 복사되는 것을 의미한다.
따라서 person.name
의 값을 변경하여도 nextPerson
은 name : "choi"
가 출력된다.
배열도 객체와 마찬가지로 기존 배열 arr1
을 변경하게되면, arr1
를 참조한 arr2
의 값 또한 변경된다.
const arr1 = [0, 1, 2, 3];
const arr2 = arr1;
arr1.shift();
console.log(arr2); // [ 1, 2, 3]이 출력됨
그러나 잠깐 헤메었던 부분이 있는데, 기존 배열에서 메소드를 통해 변경하는것과 달리 let
으로 선언되어 있는 배열 자체를 재할당 하는 경우, arr2
는 arr
가 참조되지않고, 재할당 전의 값이 복사되어있다.
let arr = [0, 1, 2, 3]
let arr2 = arr
arr = [3, 2, 1, 0]
console.log(arr2) // [0, 1, 2, 3]이 출력됨
이러한 이유를 몰라서 우선 스오플에 질문을 올려놓은 상태
+++
직전에 올린 글을 공부하면서 작성했는데, 스오플에 달린 댓글과 공부 내용을 통해 이해하게 되었다.
arr2
는 arr
와 같이 배열[0, 1, 2, 3]
의 메모리 주소의 참조를 하지만,
arr
는 단순히 새로운 배열 [3, 2, 1, 0]
에 대한 메모리 주소의 참조를 할당하게 된 것
arr2
는 여전히 [0, 1, 2, 3]
의 메모리 주소를 참조하는 것
그래서 여전히 출력값이 그대로였다 !