원시값은 값은 복사할 때 복사된 값을 다른 메모리에 할당하기 때문에 원래의 값과 복사된 값이 서로에게 영향을 미치지 않는다.
const a = 1;
let b = a;
b = 2
console.log(a); //1
console.log(b); //2
변수가 객체의 주소를 가리키는 값이기 때문에 복사된 값(주소)이 같은 값을 가리킨다.
const a = { number: 1 };
let b = a;
b.number = 2
console.log(a) //{number: 2}
console.log(b) //{number: 2}
위의 특성에 기반해 객체를 복사하는 방법은 크게 두가지로 나뉘게 된다.
객체를 복사할 때 원래값과 복사된 값이 같은 참조를 가리키고 있는 것
객체 안에 객체가 있을 경우, 한개의 객체라도 원본 객체를 참조하고 있다면 얕은복사라고 한다.
Object.assign()은 첫번째 요소로 들어온 객체에 다음 인자로 들어온 객체를 복사한다.
const obj = {
a: 1,
b: {
c: 2,
},
};
const copiedObj = Object.assign({}, obj);
copiedObj.b.c = 3
console.log(copiedObj.b.c) //3
console.log(obj.b.c) //3
obj === copiedObj // false
obj.b.c === copiedObj.b.c //true
const obj = {
a: 1,
b: {
c: 2,
},
};
const copiedObj = {...obj}
copiedObj.b.c = 3
console.log(copiedObj.b.c) //3
console.log(obj.b.c) //3
obj === copiedObj //false
obj.b.c ===copiedObj // true
깊은 복사된 객체는 객체 안에 객체가 있을 경우에도 원본과의 참조가 완전히 끊어진 객체를 말한다.
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;
}
//함수가 return 하는 것은 obj가 아닌 새로운 객체인 result => 원래값과 복사값이 서로 영향을 받지 않는다.
const copiedObj = copyObj(obj);
copiedObj.b.c = 3
console.log(obj.b.c) //2
console.log(copiedObj.b.c) //3
obj.b.c. === copiedObj.b.c //false
JSON.stringify()는 객체를 json 문자열로 변환한다. 이 과정에서 원본 객체와의 참조가 모두 끊어진다.
객체를 json 문자열로 변환 후 JSON.parse()를 이용해 다시 자바스크립트 객체로 만들어주면 깊은 복사가 된다.
🚨이 방법은 사용하기는 쉽지만 다른 방법에 비해 아주 느리다고 알려져있다.
const obj = {
a: 1,
b: {
c: 2,
},
};
const copiedObj = JSON.parse(JSON.stringify(obj));
//string(원시값)으로 변환 후 다시 객체로 만들어 주었다. => 원래값과 복사값이 서로 영향을 받지 않는다.
copiedObj.b.c = 3
console.log(obj.b.c) //2
console.log(copiedObj.b.c) //3
obj.b.c === copiedObj.b.c //false
lodash 라이브러리를 사용하면 아~~~주 쉽다.
const obj = {
a: 1,
b: {
c: 2,
},
};
const copiedObj = _.cloneDepp(obj);
copiedObj.b.c = 3;
obj.b.c === copiedObj.b.c //false