개발자 Saaad

[JavaScript] 얕은 복사, 깊은 복사 본문

학습/kakao X goorm 풀스택12회차

[JavaScript] 얕은 복사, 깊은 복사

Saaad 2024. 12. 6. 01:25

저번 포스팅 때는 얕은 비교, 깊은 비교에 대해서 알아봤는데요,

오늘은 얕은 복사, 깊은 복사에 대해서 알아봅시다.

 


 

 

 

얕은 복사

 

Spread Operator 를 이용한 얕은 복사

const aArray = [1, 2, 3];

// ... (spread operator)를 이용한 얕은 복사
const bArray = [...aArray, 4];
console.log('aArray', aArray); // [1, 2, 3]
console.log('bArray', bArray); // [1, 2, 3, 4]

console.log('aArray === bArray', aArray === bArray); 
// aArray === bArray false

aArray === bArray 가 false 인 이유는 두 배열이 참조하고 있는 주소가 다르기 때문입니다.

 

Object.assign() 을 이용한 얕은 복사

const cArray = Object.assign([], bArray);
console.log('cArray', cArray); 
// [1, 2, 3, 4]

console.log('bArray === cArray', bArray === cArray);
// bArray === cArray false

bArray === cArray 가 false 인 이유는 두 배열이 참조하고 있는 주소가 다르기 때문입니다.

 

cArray.push([5,6,7]); //[1, 2, 3, Array(3)]
const dArray = [...cArray, 10]; 
console.log(dArray); // [1, 2, 3, Array(3), 10]
dArray[4].push(8);
console.log(cArray); // [1, 2, 3, Array(4)]
console.log(dArray); // [1, 2, 3, 4, Array(4), 10]

중첩된 배열이나 객체가 있다면 cArray를 shallow copy해서 dArray를 만들고

dArray를 변경했을 때 cArray에 있는 그 중첩된 부분은 따라서 변경되는 것을 볼 수 있습니다.

 

그래서 얕은 복사 Shallow Copy라고 합니다.(깊은 부분은 복사가 되지 않으니까)

 

spread operator, Object assign 이외에도 Array.from(), slice 도 얕은 복사를 합니다.

 


얕은 동결 : Object.freeze()

Object.freeze() 메서드는 객체를 동결합니다. 동결된 객체는 더 이상 변경될 수 없습니다. 즉 동결된 객체는 새로운 속성을

추가하거나 존재하는 속성을 제거하는 것을 방지하며 존재하는 속성의 불변성, 설정 가능성, 작성 가능성이 변경되는 것을

방지하고, 존재하는 속성의 값이 변경되는 것도 방지합니다. 또한, 동결 객체는 그 프로토타입이 변경되는 것도 방지합니다.

freeze()는 전달된 동일한 객체를 반환합니다.

실행할 코드

aObject에 값을 할당 후 freeze()메소드를 사용해준 후,

aObject.a 의 값을 변경하려고 하네요. 

어떻게 될까요?

결과

aObject 는 얕은 동결을 통해 변경될 수 없는 상태이기 때문에 값이 변하지 않은 모습을 볼 수 있습니다.

 

cObject 값을 변경

이번엔 aObject의 cObject의 a를 변경하려고 합니다.

바뀔까요??

 

결과

바뀌었습니다! 얕은 동결이 수행되었기 때문에 중첩된 깊은 요소에 대해서는 동결이 되지 않은 것을 확인할 수 있습니다.

 


깊은 복사

이번에는 깊은 복사를 해보도록 하겠습니다.

 

1. JSON.Stringify();

const aObject = {
    "a": "a",
    "b": "b",
    "cObject": {"a": 1, "b": 2}
}

const newAObject = JSON.parse(JSON.stringify(aObject));
console.log('aObject:', aObject);
console.log('newAObject:', newAObject);

당연히 똑같은 값을 가진 실행 결과


이번에는 aObject의 cObject.a 값을 변화를 주어 aObject와 newObject의 값의 차이를 살펴보겠습니다.

aObject.cObject.a = 3;
console.log('aObject:', aObject);
console.log('newAObject:', newAObject);

실행결과

aObject.cObject.a 의 값은 3으로 바뀌었으나, newAObject.cObject.a 의 값은 1로 그대로인 모습입니다.

newAObject 는 깊은 복사를 통해 aObject의 값을 온전히 복사하였고, 중첩된 깊은 요소에 대해서도 aObject로부터 독립적이기

때문에 값이 함께 변하지 않았습니다.

진짜 말그대로 "복사"만 했습니다! 기존 객체로부터 영향을 받지 않습니다.

 

2. Spread Operator를 이용

// 첫번째 인자는 aObject를 복사
// 두번째 인자에서 aObject.cObject를 새로운 객체로 복사
const newAObject = {...aObject, cObject: {...aObject.cObject}};
aObject.cObject.a = 3;
console.log('aObject:', aObject);
console.log('newAObject:', newAObject);

 

실행결과

같은 결과가 나왔습니다! 

두번의 얕은 복사를 했다고 생각해도 될 것 같습니다.

첫번째 인자로 aObject를 얕은 복사를 하였고, 두번째 인자로 cObject는 ...aObject.cObject까지 얕은 복사를 한것입니다.

 

 

3. lodash 라이브러리를 이용한 깊은 복사


오늘은 깊은복사, 얕은 복사에 대해 알아봤습니다. 

감사합니다