-
TIL-2024.03.24 - JS - 얕은 복사 & 깊은 복사> 기초/Javascript 2024. 3. 24. 19:58
------- 배경
아래와 같은 원시값은 값을 복사 할 때 복사된 값을 다른 메모리에 할당 하기 때문에 원래의 값과 복사된 값이 서로에게 영향을 미치지 않음.
- 이러한 원시값들은 모두 변경이 불가능하며, 각각의 자체적인 데이터 가짐.
- 예를 들어, 변수에 원시값을 할당하면 변수에는 해당 원시값이 직접 저장되기에 한 변수의 값을 변경해도 다른 변수에 영향 없음.
(string, number, boolean, undefined, null, symbol)
const a = 1; let b = a; b = 2 console.log(a); //1 console.log(b); //2
하지만 참조값 (Object & Array)은 변수가 객체의 주소를 가리키는 값이기 때문에 복사된 값(주소)이 같은 값을 가리킴.
// 객체 var person = { name: "John", age: 30 }; var anotherPerson = person; // 객체 참조값 복사 anotherPerson.name = "Jane"; // anotherPerson을 변경 console.log(person.name); // 출력: "Jane" - 원본 객체도 변경됨 // 배열 var fruits = ["Apple", "Banana", "Orange"]; var otherFruits = fruits; // 배열 참조값 복사 otherFruits[0] = "Grapes"; // otherFruits를 변경 console.log(fruits[0]); // 출력: "Grapes" - 원본 배열도 변경됨
> 특징 때문에 객체를 복사하는 방법은 크게 두가지 (얕은 복사, 깊은 복사)로 나뉜다.
------- 얕은 복사 (Shallow Copy)
- 얕은 복사는 원본 객체의 속성을 새로운 객체로 복사하지만, 그 속성들이 객체일 경우에는 참조 주소만 복사.
- 즉, 원본 객체와 복사본 객체는 동일한 객체를 참조 >이는 복사된 객체가 원본 객체의 변경에 영향을 받을 수 있음을 의미.
방법:
1. Object Assign
// Object Assign const obj = { a: 1, b: { c: 2, }, }; const copiedObj = Object.assign({}, obj); copiedObj.b.c = 3 obj === copiedObj // false obj.b.c === copiedObj.b.c // true
2. Spread Operator
// Spread Operator const obj = { a: 1, b: { c: 2, }, }; const copiedObj = {...obj} copiedObj.b.c = 3 obj === copiedObj // false obj.b.c === copiedObj.b.c // true
2-1. 주의
// 내가 몰랐던 부분 const obj = { a: 1, b: { c: 2, }, }; const copiedObj = {...obj} copiedObj.b.c = 3 copiedObj.a = 5 console.log(copiedObj) // {a: 5, b:{c:3}} console.log(obj) // {a: 1, b:{c:3}} // => 여기서 // copiedObj.b.c = 3 // copiedObj.a = 5 // 한 경우 obj.b.c 는 3으로 변경되었는데 obj.a 는 변경안됨 // 왜?
이유:
더보기- JS에서 Spread Operator를 사용하여 얕은 복사를 수행하면 외부 구조만 복사, 내부 객체는 원본 객체와 같은 참조를 유지.
- 따라서 copiedObj는 obj의 복사본이지만, 내부 객체는 동일한 객체를 참조.
- 여기서 copiedObj.b.c = 3를 실행하면, copiedObj의 내부 객체인 b의 c 프로퍼티가 변경.
- 하지만 이 내부 객체 b는 원본 객체 obj와 공유되기 때문에, obj.b.c도 변경.
- 그러나 copiedObj.a = 5를 실행하면, copiedObj의 a 프로퍼티를 변경하면서 새로운 값을 할당.
- 이 작업은 obj의 외부 객체인 a 프로퍼티와는 별개의 작업이므로, obj 객체는 변경되지 않습니다.
> 즉, copiedObj의 변경이 obj에 영향을 미치는 것은 내부 객체에 대한 변경일 때만 해당되며, 외부 객체에 대한 변경은 별개의 작업으로 처리됩니다.
> TIL-2024.03.25 - JS - 외부객체와 내부객체 참조 (중요)
https://heathworld.tistory.com/105
------- 깊은 복사 (Deep Copy)
- 깊은 복사는 모든 단계의 객체와 속성을 완전히 복사 > 따라서 원본 객체의 변경이 복사본에 영향 없음.
1. JSON.Parse(JSON.stringify(obj))
// JSON.parse & JSON.stringify const obj = { a: 1, b: { c: 2, }, }; const copiedObj = JSON.parse(JSON.stringify(obj)); copiedObj.b.c = 3 obj.b.c === copiedObj.b.c //false
2. lodash > cloneDeep
const obj = { a: 1, b: { c: 2, }, }; const copiedObj = _.cloneDeep(obj); copiedObj.b.c = 3 obj.b.c === copiedObj.b.c //false
'> 기초 > Javascript' 카테고리의 다른 글
TIL-2024.03.26 - Vue - Web Rendering & Vue 작용 (0) 2024.03.26 TIL-2024.03.25 - JS - 외부 객체와 내부 객체 (0) 2024.03.25 TIL-2024.03.22 - JS - Closure (0) 2024.03.22 TIL-2024.03.19 - JS - 이벤트 버블링 & 캡처링 (0) 2024.03.19 TIL-2024.02.27 - JS - 실행 컨텍스트-4. 렉시컬 환경-3 (0) 2024.02.27