얕은 복사와 깊은 복사는 객체를 복사할 때 사용되는 개념이다.
let obj1 = { a: 1, b: 2 };
let obj2 = obj1; // 얕은 복사
obj2.a = 3;
console.log(obj1.a); // 3
객체를 그대로 복사하여 사용하면 원본 객체의 데이터가 변경될 수 있기 때문에 객체의 값을 복사하고 사용하고 싶다면 얕은 복사가 아닌 깊은 복사를 사용하는 것이 좋다.
1.Object.assign() 함수 사용
let obj1 = { a: 1, b: 2 };
let obj2 = Object.assign({}, obj1); // 깊은 복사
obj2.a = 3;
console.log(obj1.a); // 1 -> 원본값 보존됨
console.log(obj2.a); // 3
1차원 객체는 원본값이 보존되는 깊은 복사가 이루어졌다
하지만 2차원 객체를 복사할 때는 깊은 복사가 이루어지지 않는다
const obj = {
a: 1,
b: { c: 2 },
}
const copyObj = Object.assign({}, obj);
copyObj.b.c = 3;
console.log(obj); // { a: 1, b: { c: 3 } } -> 오잉 원본값이 변경됐다
console.log(obj.b.c === copyObj.b.c); // true
이는 복사된 하위 객체 {c: 2}도 결국 객체이기 때문에 얕은 복사가 된 것이다.
그래서 Object.assign() 메서드는 1차원 객체만 깊은 복사 해야한다.
2.전개 연산자(Spread Operator)
const obj = {
a: 1,
b: { c: 2 },
};
const copyObj = {...obj};
copyObj.b.c = 3;
console.log(obj); // { a: 1, b: { c: 3 } }
console.log(obj.b.c === copyObj.b.c); // true
전개 연산자도 Object.assign()와 마찬가지로 2차원 객체는 얕은 복사가 된다.
3. JSON의 stringify()와 parse()
문자열로 만들고 다시 객체로 만든다. (모두 새 주소를 갖게 된다.)4. lodash 라이브러리의 cloneDeep()
const obj = {
a: 1,
b: { c: 2 },
func: function () {
return this.a;
}
};
const copyObj = lodash.cloneDeep(obj);
copyObj.b.c = 3;
console.log(obj); // { a: 1, b: { c: 2 }, func: [Function: func] }
console.log(obj.b.c === copyObj.b.c); // false