[TIL] Object Copy
Object Copy
자바스크립트에서 값은 원시값과 참조값으로 나뉩니다.
원시값
- Number
- String
- Boolean
- null
- undefined
- Symbol
원시값은 값을 복사할 때 복사된 값을 다른 메모리에 할당하기 때문에 원래의 값과 복사된 값이 서로에게 영향을 미치지 않습니다.
const a = 1;
let b = a;
b = 2;
console.log(a); // 1;
console.log(b); // 2;
참조값
- Object
하지만 참조값은 변수가 객체의 주소를 가리키는 값이기 때문에 복사된 값(주소)이 같은 값을 가리킵니다.
const a = {number: 1};
let b = a;
b.number = 2;
console.log(a); // {number: 2};
console.log(b); // {number: 2};
이러한 객체의 특징 때문에 객체를 복사하는 방법은 크게 두가지로 나뉩니다.
얕은 복사(Shallow copy)
얕은 복사란 객체를 복사할 때 원래값과 복사된 값이 같은 참조를 가리키고있는 것을 말한다. 객체 안에 객체가 있을 경우 한개의 객체라도 원본 객체를 참조하고 있다면 이를 얕은 복사라고 한다. 얕은 복사를 하는 방법은 다음과 같다.
Array.prototype.slice
주로 배열을 복사할 때 사용할 수 있습니다. Array.prototype.slice
는 start부터 end까지 대상 배열에서 꺼내와 새로운 배열을 만들어 값을 집어넣습니다. 간단한 방법이지만, 중첩 구조 복사를 제대로 수행할 수 없다는 단점이 있습니다.
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
전개연산자(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
깊은 복사(Deep copy)
깊은 복사된 객체는 객체안에 객체가 있을 경우에도 원본과의 참조가 완전히 끊어진 객체를 말한다. 깊은 복사를 하는 방법은 다음과 같다.
재귀함수를 이용한 복사
const obj = {
a: 1,
b: {
c: 2,
},
};
function copyObj(obj) {
const result = {};
for (let key in obj) {
if (typeof obj[key] === 'object') {
result[key] = copyObj(obj[key]);
} else {
result[key] = obj[key];
}
}
return result;
}
const copiedObj = copyObj(obj);
copiedObj.b.c = 3;
obj.b.c === copiedObj.b.c //false
JSON.stringify()
JSON.stringify()
는 객체를 json 문자열로 변환하는데 이과정에서 원본 객체와의 참조가 모두 끊어집니다. 객체를 json 문자열로 변환후 JSON.parse()
를 이용해 다시 자바스크립트 객체로 만들어주면 깊은 복사가 됩니다.
하지만, BigInt
의 경우 JSON.stringify()
를 원래 통과해야 정상이지만, JSON.parse()
로 다시 원상복귀할 때 어떻게 값을 복원시킬 것인지에 대한 코드 처리가 없기 때문에 완전한 깊은 복사를 할 수 없습니다.
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
라이브러리 사용
lodash
와 ramda
라이브러리를 사용하면 깊은 복사를 더 쉽게 할 수 있다고 합니다.
const obj = {
a: 1,
b: {
c: 2,
},
};
const copiedObj = _.cloneDeep(obj);
copiedObj.b.c = 3;
obj.b.c === copiedObj.b.c //false
Reference
[Javascript] 얕은 복사, 깊은 복사
[JS] 원시 타입(Primitive Type)과 참조 타입(Reference Type)의 변수 복사 비교
What is the difference between a deep copy and a shallow copy?
깊은 복사와 얕은 복사에 대한 심도있는 이야기
Author And Source
이 문제에 관하여([TIL] Object Copy), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@shallwedance/TIL-Object-Copy저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)