얕은 복사(Shallow Copy)와 깊은 복사(Deep Copy) - (JavaScript)

Jiwonp·2023년 2월 27일
1

JavaScript 정리

목록 보기
2/6
post-thumbnail

🔥 배열의 복사

다시 얘기하지만 배열은 참조 자료형 데이터 타입이다.

자바스크립트에서 기본 데이터 타입(원시 타입)으로는
string, number, null, undefined, symbol이 존재한다.

참조형 데이터 타입으로는 Array와 Object가 존재한다.


🔥 얕은 복사

사본을 만들어내지 않고 원본을 참조하도록 복사한 척을 하는 것

기본형에서 얕은 복사

기본 데이터 타입에서 복사한 데이터를 변경할 때 원본은 변경되지 않는다.

var a = 10;
var b = a; // (1)

console.log(a); // 10
console.log(b); // 10

b = 5; // (2)

console.log(a); // 10
console.log(b); // 5

(1)

두 변수는 서로 같은 주솟값(@5003)을 참조

(2)

원본의 주소(@5003)를 참조하고 있었지만 새로운 데이터로 변경할 때 데이터 영역에서 새로운 데이터를 할당하고(@5004) 그 주솟값을 다시 참조


참조형에서 얕은 복사

var arr1 = [1, 2, 3, 4];
var arr2 = arr1; // (1)

console.log(arr1); // [1, 2, 3, 4]
console.log(arr2); // [1, 2, 3, 4]

arr2[0] = 0; // (2)

console.log(arr1); // [0, 2, 3, 4]
console.log(arr2); // [0, 2, 3, 4]

(1)

두 변수는 서로 같은 주솟값(@5003)을 참조

@5003에 데이터를 저장하려고 보니 여러 개의 프로퍼티로 이뤄진 데이터 그룹이다. 이 그룹 내부의 프로퍼티들을 저장하기 위해 별도의 변수 영역을 마련하고, 그 영역의 주소 @7001 ~ ?를 @5003에 저장

(2)

arr2 가 arr1 과 같은 값을 참조하고 있기 때문에 사본인 arr2 에서 배열의 요소를 수정했을 때 원본에도 수정이 일어남.

@5002가 참조하는 값중 @7001의 값의 주소가 바뀜.
arr1, arr2는 같은 주솟값 @5002를 참조함.
이때 @5004의 값인 1은 참조 카운트가 0인 메모리 주소기 때문에 가비지 컬렉터의 수거 대상이 됨.


🔥 깊은 복사

완벽하게 원본과 사본을 나눠 복사하는 방법

spread operator

let arr1 = [1, 2, 3];
let arr2 = [...arr1];

arrB[0] = 10;

console.log(arr1); // [1, 2, 3]
console.log(arr2); // [10, 2, 3]

한단계 까지의 깊은 복사만 적용. (다차원 배열X)
두단계 이상의 depth부터는 참조 값을 전달하는 얕은복사를 진행함.


JSON.stringify(), JSON.parse()

다차원 배열을 복사해야 하는 경우 JSON.stringify() 함수로 원본 배열을 문자열로 변환 후 JSON.parse() 함수로 JavaScript Object로 파싱 한다.

let arr1 = [[1, 2, 3], ['A', 'B', 'C']];
let arr2 = JSON.parse(JSON.stringify(arr1));

arrB[0][0] = 10;

console.log(arrA); // [[1, 2, 3], ['A', 'B', 'C']]
console.log(arrB); // [[10, 2, 3], ['A', 'B', 'C']]

외부 라이브러리 사용

완전한 깊은 복사를 반드시 해야 하는 경우라면, node.js 환경에서 외부 라이브러리인 lodash, 또는 ramda를 설치하면 된다. 다음은 lodash의 cloneDeep을 사용한 깊은 복사의 예시이다.

const lodash = require('lodash');

const arr = [1, 2, [3, 4]];
const copiedArr = lodash.cloneDeep(arr);

console.log(arr); 					  // [1, 2, [3, 4]]
console.log(copiedArr); 			  // [1, 2, [3, 4]]
console.log(arr === copiedArr) 		  // false
console.log(arr[2] === copiedArr[2])  // false

.slice() // 주소가 다르기 때문에 복사한 배열에 요소를 추가해도 원본 배열에는 변화x

얕은 복사를 하지만 새로운 배열을 만드는 아이들이 많은것같은데... 이 부분에 대해서는 공부를 많이 해봐야겠당...🫥🫥🫥

profile
매일 풀타임 코딩

0개의 댓글