얕은 복사와 깊은 복사
객체의 특징
객체는 복사할 때 원시 타입(문자열, 숫자, 불린값)가 다른 방식을 사용한다.
객체를 아래 코드처럼 복사하게 되면
let user = { name: "John" };
let admin = user; // 참조값을 복사함
참조 값을 복사하게 된다.
이는 user에서 객체를 저장하고 있는 위치를 admin에게 알려줘서 참조값을 복사하는 것이다.
이렇게 된다면 admin을 수정했을 때, user의 값도 바뀌게 된다.
그리고 user와 admin을 '==', '===' 연산자로 비교하면 true가 나오게 된다. (객체는 '=='도 '==='와 동일하게 동작)
얕은 복사
얕은 복사는 객체를 복사할 때 기존 값과 복사된 값이 같은 참조를 가리키는 것을 말한다. 객체 안의 한 객체라도 기존 변수의 객체를 참조하고 있으면 이를 얕은 복사라고 한다.
1. Object.assign
const obj = {
a: 1,
b: {
c: 2,
},
};
const copiedObj = Object.assign({}, obj);
copiedObj.b.c = 3;
console.log(obj === copiedObj); // false
console.log(obj.b.c === copiedObj.b.c); // true
Object.assign(a, b)는 a 객체에 b 객체를 복사해주는 것이다.
obj와 copiedObj는 서로 다른 객체에 복사된 것이라 서로 독립적인 복제본이 되었지만 안의 b 객체는 서로 같은 값을 참조하고 있다.
2. 스프레드 연산자
const obj = {
a: 1,
b: {
c: 2,
},
};
const copiedObj = {...obj}
copiedObj.b.c = 3
console.log(obj === copiedObj); // false
console.log(obj.b.c === copiedObj.b.c) // true
여기서도 마찬가지로 obj와 copiedObj의 b 객체는 같은 값을 참조하고 있어서 위 같은 결과가 나온다.
깊은 복사
깊은 복사된 객체는 객체안에 객체가 있어도 원본과 참조가 완전 끊긴 객체를 의미한다.
1. 재귀함수를 이용한 복사
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;
console.log(obj.b.c === copiedObj.b.c); //false
이 코드처럼 재귀함수를 이용해서 복사하면 두 객체간의 참조가 끊겨서 "obj.b.c === copiedObj.b.c"의 결과가 false가 나온다.
2. _.cloneDeep
var objects = [{ 'a': 1 }, { 'b': 2 }];
var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]);
// => false
js의 lodash의 메서드인 _.cloneDeep를 사용하면 반복문을 사용하지 않아도 깊은 복사를 할 수 있다.
3. JSON.stringify()
const obj = {
a: 1,
b: {
c: 2,
},
};
const copiedObj = JSON.parse(JSON.stringify(obj));
copiedObj.b.c = 3;
console.log(obj.b.c === copiedObj.b.c); //false
객체를 json으로 변경하는 과정에서 참조가 모두 끊긴다. JSON.parse()를 이용해 다시 객체로 만들어주면 깊은 복사가 된다.
-참고 사이트
https://ko.javascript.info/object-copy
참조에 의한 객체 복사
ko.javascript.info
[Javascript] 얕은 복사, 깊은 복사
자바스크립트에서 값은 원시값과 참조값으로 나뉜다. 원시값 Number String Boolean Null Undefined 참조값 Object Symbol 원시값은 값을 복사 할 때 복사된 값을 다른 메모리에 할당 하기 때문에 원래의 값과
velog.io