반응형
객체의 가변성
const originalArr = [1, 2, 3, 4, 5];
let copiedArr = originalArr;
console.log(originalArr === copiedArr);
copiedArr[0] = 6;
console.log(originalArr, copiedArr); // [6,2,3,4,5] , [6,2,3,4,5]
- 위의 코드처럼 원본 객체는 그대로 두고 싶은 상황에서 복사본이 변경될 때 원본도 같이 변하는 문제점이 발생할 때가 있습니다. 이는 객체의 가변성으로 인해 생기는 문제입니다.
== VS ===
==은 값이 같은지만 비교하고, ===은 값과 타입이 같은지를 모두 비교합니다.
let a = 1;
let b = "1"
console.log(a == b); // true
console.log(a === b); // false
- 값은 같기 때문에 ==은 true이고 타입이 다르기 때문에 === 에선 false가 출력됩니다.
let arrayA = [1,2,3,4];
let arrayB = [1,2,3,4];
let arrayC = arrayA;
console.log(arrayA == arrayB); // false
console.log(arrayB == arrayC); // false
console.log(arrayA == arrayC); // true
console.log(arrayA === arrayC); // true
- 참조값 타입에선 참조하는 주솟값을 비교합니다. arrayC는 arrayA가 바라보고 있는 참조값을 복사했기 때문에 true를 반환하게 됩니다.
얕은 복사 (Shallow Copy)
얕은 복사는 객체의 바로 아래 단계인 1 Depth 값만 복사하는 방식입니다. 즉, 1 Depth가 넘어가면 원본과 사본이 동일한 주소를 가리키게 되어 둘 중 한 곳이라도 변경되면 같이 변경되게 됩니다.
let copyArray = function(target) {
let result = [];
for (let prop in target) {
result.push(target[prop]);
}
return result;
}
let originalArr = [1, 2, 3, 4, 5];
let copiedArr = copyArray(originalArr);
console.log(originalArr === copiedArr);
copiedArr[0] = 6;
console.log(originalArr, copiedArr); // [1,2,3,4,5] , [6,2,3,4,5]
- 다음과 같이 주솟값을 참조하지 않고, 값을 직접 넣어주는 방식을 사용한다면, 원본과 분리해서 배열을 복사할 수 있습니다.
let originalArr = [1, 2, 3, 4, 5];
let copiedArr = originalArr.map((item) => item);
console.log(originalArr === copiedArr);
copiedArr[0] = 6;
console.log(originalArr, copiedArr); // [1,2,3,4,5] , [6,2,3,4,5]
- map 함수를 사용해도 얕은 복사를 통해 객체를 복사할 수 있습니다.
function copyObject(target) {
let result = {};
for (let prop in target) {
result[prop] = target[prop];
}
return result;
}
let personA = {
name: "sasca",
blog: {
url: "https://sasca37.tistory.com"
}
}
let personB = copyObject(personA);
console.log(personA, personB);
personB.name = "sasca37"; // B만 변경 - 1 Depth
personB.blog.url = ""; // A와 B 모두 변경 - 2 Depth
console.log(personA, personB);
- 1 Depth 까지는 얕은 복사를 통해서 실제 값을 가져올 수 있지만, 2 Depth 부터는 실제 값이 아닌 주솟값을 가리키기 때문에 한쪽이 변경되면 다른 한쪽도 같이 변경됩니다.
깊은 복사 (Deep Copy)
깊은 복사는 객체의 모든 속성을 값으로 복사하는 것을 의미합니다. 따라서 프로퍼티가 2 Depth 이상이면서 참조형 데이터 인경우 내부 값을 재귀적으로 찾아와서 복사해주어야 합니다.
function deepCopyObject(target) {
let result = {};
if (typeof target === 'object' && target !== null) {
for (let prop in target) {
result[prop] = deepCopyObject(target[prop]);
}
} else {
result = target;
}
return result;
}
- 다음과 같이 deepCopy를 할 수 있도록 재귀적으로 프로퍼티들을 순회하면서 값을 넣어주면 깊을 복사를 한 객체 본사본을 만들 수 있습니다.
let personA = {
name: "sasca",
blog: {
url: "https://sasca37.tistory.com"
}
}
let personB = deepCopyObject(personA);
personB.name = "sasca37"; // B만 변경 - 1 Depth
personB.blog.url = ""; // B만 변경 - 2 Depth
console.log(personA, personB);
- 재귀적으로 모든 프로퍼티에 값을 넣어주었기 때문에 2 Depth 이상에도 깊은 복사를 할 수 있어요.
let personA = {
name: "sasca",
blog: {
url: "https://sasca37.tistory.com"
}
}
let personB = JSON.parse(JSON.stringify(personA));
personB.name = "sasca37"; // B만 변경
personB.blog.url = ""; // B만 변경
console.log(personA, personB);
- 객체를 JSON 으로 변환했다가 다시 객체로 변환하면 깊은 복사를 처리할 수 있습니다. 단, 메서드나 숨겨진 프로퍼티 등은 제외됩니다.
반응형