객체와 배열을 복사하는 방법

chosey·2022년 11월 22일
0

React

목록 보기
4/4

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 의 값을 변경하여도 nextPersonname : "choi" 가 출력된다.


배열

배열도 객체와 마찬가지로 기존 배열 arr1 을 변경하게되면, arr1 를 참조한 arr2 의 값 또한 변경된다.

const arr1 = [0, 1, 2, 3];
const arr2 = arr1;

arr1.shift();

console.log(arr2); // [ 1, 2, 3]이 출력됨

그러나 잠깐 헤메었던 부분이 있는데, 기존 배열에서 메소드를 통해 변경하는것과 달리 let으로 선언되어 있는 배열 자체를 재할당 하는 경우, arr2arr 가 참조되지않고, 재할당 전의 값이 복사되어있다.

let arr = [0, 1, 2, 3]
let arr2 = arr

arr = [3, 2, 1, 0]

console.log(arr2) // [0, 1, 2, 3]이 출력됨

이러한 이유를 몰라서 우선 스오플에 질문을 올려놓은 상태

https://stackoverflow.com/questions/74528273/why-is-the-previous-value-copied-instead-of-a-pointer-in-javascript

+++

궁금증 해결

직전에 올린 글을 공부하면서 작성했는데, 스오플에 달린 댓글과 공부 내용을 통해 이해하게 되었다.

arr2arr 와 같이 배열[0, 1, 2, 3] 의 메모리 주소의 참조를 하지만,

arr 는 단순히 새로운 배열 [3, 2, 1, 0] 에 대한 메모리 주소의 참조를 할당하게 된 것

arr2는 여전히 [0, 1, 2, 3]의 메모리 주소를 참조하는 것

그래서 여전히 출력값이 그대로였다 !

결론

React에서든 일반 JS에서든 배열이나 객체를 복사할 때에는 이들이 참조형 데이터 타입이라는 것을 유의하고 실수하지않도록 조심해야한다.

profile
chosey

0개의 댓글