원시 값과 참조 값을 복습하며 오늘은 얕은 복사와 깊은 복사를 좀 더 알아보자. 이들은 프로그래밍에서 참조 값을 처리할 때 사용되는 개념이며 객체를 복사할 때 사용함.
참조 값의 복사!
한 데이터를 공유
하는 것.한 단계까지만 복사
하는 것.const obj1 = { a: 1,
b: {
c: 2
}
};
// Object.assign()
const obj2 = Object.assign({}, obj1);
// Spread Operator
const obj3 = { ...obj1 };
console.log(obj1 === obj2); // Output: false
console.log(obj1 === obj3); // Output: false
// 얇은 복사로 객체 복사 -> 원본 !== 복사본
console.log(obj1.a === obj2.a); // Output: true
console.log(obj1.b === obj3.b); // Output: true
// 1depth 까지 복사 되기 때문에 2depth 이상을 비교해보면 원본과 복사본의 값이 같다고 나옴.
obj1.a = 100;
console.log(obj1.a); // Output: 100 (변경 됨)
console.log(obj2.a); // Output: 1 (변경 없음)
console.log(obj3.a); // Output: 1 (변경 없음)
// 원본 객체(obj1)의 가장 상위 속성 a의 값을 변경함.
// 얕은 복사는 최상위 속성의 값들이 복사되어 저장됨.
// 변경된 원본 객체(obj1)와 복사본 객체(obj2, obj3) 간에 상위 속성 a의 값이 독립적으로 존재. 따라서 원본 객체의 속성 a 값 변경은 복사본 객체에 영향을 주지 않음.
obj2.b.c = 200;
console.log(obj1.b.c); // Output: 200 (변경 됨)
console.log(obj2.b.c); // Output: 200 (변경 됨)
console.log(obj3.b.c); // Output: 200 (변경 됨)
// 복사본 객체(obj2)의 중첩 객체의 속성(b.c) 값을 변경.
// 얕은 복사는 중첩 객체의 참조값을 공유함.
// 따라서 원본 객체(obj1)와 복사본 객체(obj2)의 중첩 객체 속성 b는 동일한 객체를 참조, 복사본 객체의 속성 b.c 값 변경은 원본 객체와 다른 복사본 객체(obj3)에도 영향을 미침.
// 배열은 slice, concat 등을 사용해 복사할 수 있음.
const arr1 = [1,
2, {
a: 3
}
];
const arr2 = arr1.slice();
const arr3 = arr1.concat();
arr1[0] = 100;
console.log(arr1[0]); // Output: 100 (변경 됨)
console.log(arr2[0]); // Output: 1 (변경 없음)
console.log(arr3[0]); // Output: 1 (변경 없음)
arr2[2].a = 300;
console.log(arr1[2].a); // Output: 300 (변경 됨)
console.log(arr2[2].a); // Output: 300 (변경 됨)
console.log(arr3[2].a); // Output: 300 (변경 됨)
실제 값 자체가 복사되는 것!
객체에 중첩되어있는 객체까지 모두 복사
하는 것.const originalObj = {
a: 1,
b: {
c: 2,
},
};
const deepCopiedObj = JSON.parse(JSON.stringify(originalObj));
// JSON.stringify()를 사용 원본 객체를 JSON 문자열로 변환하고 JSON.parse()를 사용 JSON 문자열을 다시 객체로 변환하여 깊은 복사를 수행.
// JSON.parse()와 JSON.stringify()를 사용한 깊은 복사의 경우 원본 객체에 함수, undefined, Symbol, 순환 참조 등이 포함된 경우 사용할 수 없음. 이런 경우에는 재귀 함수 또는 외부 라이브러리를 사용할 것.
console.log(deepCopiedObj); // Output: { a: 1, b: { c: 2 } }
// 재귀 함수를 사용한 깊은 복사
function deepCopy(obj) {
if (typeof obj !== 'object' || obj === null) {
return obj;
}
const copy = Array.isArray(obj) ? [] : {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
copy[key] = deepCopy(obj[key]);
}
}
return copy;
}
const copiedObject = deepCopy(originalObj);
console.log(copiedObject); // Output: { a: 1, b: { c: 2 } }
// 이 밖에 Lodash 라이브러리의 cloneDeep() 메서드를 이용해 깊은 복사를 할 수 있음.
import _ from 'lodash';
const deepCopiedObject = _.cloneDeep(deepCopiedObject);