TIL-36, Shallo Copy, Deep Copy
얕은 복사와 깊은 복사가 무엇인지 알아보자.
얕은 복사 (Shallow Copy)
참조(주소)값의 복사.
해당 데이터의 주소값을 전달하여 하나의 데이터를 공유한다.
객체의 얕은 복사
let obj = { value: 1};
let obj2 = obj;
obj2.value = 2;
console.log(obj.value) // 2
console.log(obj2.value) // 2
console.log(obj.value === obj2.value) // true
배열의 얕은 복사
let arr = [1, 2, 3];
let arr2 = arr;
arr2.push(4);
console.log(arr) // [1, 2, 3, 4]
console.log(arr2) // [1, 2, 3, 4]
console.log(arr === arr2) // true
깊은 복사 (Deep Copy)
값 자체의 복사.
아래 코드처럼 원시 자료형은 깊은 복사가 된다.
독립적인 메모리에 값 자체를 할당하고 생성하는 것이다.
let a = 1;
let b = a;
b = 2;
console.log(a); // 1;
console.log(b); // 2;
console.log(a === b); // false
그렇다면 참조 자료형인 객체의 값을 바꾸지 않고 (immutable) 활용하는 방법은 무엇이 있을까?
참조 자료형의 깊은 복사
- 객체 메소드
Object.assign()
을 이용하는 방법,
객체 메소드인 Object.assign()
의 첫번쨰 인자로 빈 객체 {} 를 넣어주고,
다음 인자로 활용할 객체를 넣어준다.
배열 메소드 concat()
을 이용해 배열의 깊은 복사를 이루어낸다.
객체의 깊은 복사
let obj = { value: 1};
let obj2 = Object.assign({}, obj);
obj2.value = 2;
console.log(obj.value) // 1
console.log(obj2.value) // 2
console.log(obj.value === obj2.value) // false
------------------------------------------------
배열의 깊은 복사
let arr = [1, 2, 3];
let arr2 = [].concat(arr);
arr2.push(4);
console.log(arr) // [1, 2, 3]
console.log(arr2) // [1, 2, 3, 4]
console.log(arr === arr2) // false
위와 같이 객체에서 Object.assign() 메소드를 이용하면, 기존 obj의 값이 변하지 않는 깊은 복사가 이루어지고, 배열에서 concat() 메소드를 이용하면 기존 arr의 값이 변하지 않는 깊은 복사가 이루어진다.
- 전개 연산자 (Spread Operator)를 이용하는 방법.
객체의 깊은 복사
let obj = { value: 1};
let obj2 = {...obj};
obj2.value = 2;
console.log(obj.value) // 1
console.log(obj2.value) // 2
console.log(obj.value === obj2.value) // false
------------------------------------------------
배열의 깊은 복사
let arr = [1, 2, 3];
let arr2 = [...arr];
arr2.push(4);
console.log(arr) // [1, 2, 3]
****console.log(arr2) // [1, 2, 3, 4]
console.log(arr === arr2) // false
위와 같이 깊은 복사를 이루어낼 수 있지만,
객체의 경우 2차원 객체의 깊은 복사는 이루어지지 않는다.
let obj = { a: 1, b: { c: 2 } };
let obj2 = Object.assign({}, obj);
obj.b.c = 3;
console.log(obj.b.c); // 3
console.log(obj2.b.c); // 3
console.log(obj.b.c === obj2.b.c); // true
이 문제는 전개 연사자 역시 마찬가지이다.
let obj = { a: 1, b: { c: 2 } };
let obj2 = { ...obj };
obj.b.c = 3;
console.log(obj.b.c); // 3
console.log(obj2.b.c); // 3
console.log(obj.b.c === obj2.b.c); // true
그렇다면 2차원 객체의 깊은 복사는 어떻게 행해야할까?
JSON 메소드를 이용한 2차원 객체의 깊은 복사
let obj = { a: 1, b: { c: 2 } };
let obj2 = JSON.parse(JSON.stringfy(obj));
obj2.b.c = 3;
console.log(obj.b.c); // 2
console.log(obj2.b.c); // 3
console.log(obj.b.c === obj2.b.c); // false
하지만, JSON 메소드를 사용하는 것 역시 문제점이 있는데,
다른 방법들에 비해 속도가 느리다는 성능적인 문제와,
JSON.stringify() 메소드는 함수를 만났을 때 undefined를 반환하기 때문에 범용성이
떨어진다는 점이다.
더 효율적인 객체의 깊은 복사는 앞으로 공부하며 더 알아보도록 하자!