- 얕은 복사 (Shallow copy)
주소 값을 복사하기 때문에 참조하고 있는 실제 값이 같음- 깊은 복사 (Deep copy)
실제 값을 독립적인 새로운 메모리 공간에 복사, 참조를 공유하지 않음
참고로 아래 두 가지 얕은 복사 방식의 경우 1차원 객체일 때에는 깊은 복사된다.
const obj = {
a: 1,
b: {
c: 2,
}
}
const newObj = Object.assign({}, obj);
// newObj의 값을 변경했을 때
newObj.b.c = 99;
console.log(obj === newObj); // false
console.log(obj.b.c); // 99
console.log(obj.b.c === newObj.b.c); // true
obj === newObj
가 false
인 것으로 보아 두 객체는 다른 참조 값을 갖는다. 따라서 newObj의 c의 값을 변경했을 때, obj의 c 값은 변화가 없어야 한다.
그런데 obj의 c 값도 99로 변경되었다.
이러한 현상이 일어나는 이유는 2차원 이상의 객체일 때 내부 객체는 깊은 복사가 되지 않기 때문이다.
const obj = {
a: 1,
b: {
c: 2,
}
}
const newObj = {...obj};
newObj.b.c = 99;
console.log(obj === newObj); // false
console.log(obj.b.c); // 99
console.log(obj.b.c === newObj.b.c); // true
스프레드 연산자도 2차원 객체는 깊은 복사를 하지 못했다.
JSON.stringify() 메서드를 통해 String 타입으로 변환 후, JSON.parse() 메서드로 다시 객체로 변환해준다.
이 과정에서 두 객체의 참조 관계는 완전히 끊기게 된다.
const obj = {
a: 1,
b: {
c: 2,
}
}
const newObj = JSON.parse(JSON.stringify(obj))
newObj.b.c = 99;
console.log(obj === newObj); // false
console.log(obj.b.c); // 2
console.log(obj.b.c === newObj.b.c); // false
이 방법의 단점은 ladash 라이브러리를 따로 설치해야 한다는 점이다.
const obj = {
a: 1,
b: {
c: 2,
},
};
const newObj = _.cloneDeep(obj);
newObj.b.c = 99;
console.log(obj === newObj); // false
console.log(obj.b.c); // 2
console.log(obj.b.c === newObj.b.c); // false
const deepCopy = (obj) => {
if (obj === null || typeof obj !== "object") {
return obj;
}
let copy = {};
for (let key in obj) {
copy[key] = deepCopy(obj[key]);
}
return copy;
}
const obj = {
a: 1,
b: {
c: 2,
},
func: function () {
return this.a;
},
};
const newObj = deepCopy(obj);
newObj.b.c = 99;
console.log(obj === newObj); // false
console.log(obj.b.c); // 2
console.log(obj.b.c === newObj.b.c); // false
JSON.strigify()를 사용할 경우
값이 undefined인 경우 => property 탈락
값이 NaN인 경우 => null 로 변경
이걸 모르고 쓰면 디버깅이 힘들질 수 있습니다. 방법 중 1가지 일뿐 만능아니란 점
이글을 읽으신 분들께 도움이 되셨으면 좋겠습니다.