자바스크립트에서 배열이나 객체를 복제할 때 고려해야 할 얕은 복제(Shallow Copy)와 깊은 복제(Deep Copy)에 대해 알아본다.
우선 자바스크립트의 Data Type에는 Primitive Type과 Reference Type이 있다는 것을 알고 있을 것이다.
Primitive Type과는 달리 Reference Type를 변수에 할당하면 데이터를 자체를 저장되지 않고 않고, 그 데이터에 대한 참조가 저장된다.
let arr1 = [];
let arr2 = [];
console.log(arr1 === arr2) //false
//겉보기에는 같은 배열 같아보인다.
//하지만 이 경우 arr1과 arr2가 참조하고 있는 값이 다르기 때문에,
//arr1과 arr2는 다르다.
arr1.push(1)
//따라서 arr1을 변형시켜도
console.log(arr2) // []
//arr2는 영향을 받지 않는다.
let x = [1, 2, 3, 4];
let y = x; //변수 x에 저장된 배열 객체의 참조가 y변수에 할당되었다.
y.push(5); //y 배열에 5를 푸시한다.
console.log(x); //[1,2,3,4,5]
//x와 y의 참조 값이 같다.
//따라서 y를 변형시키면, x 또한 변화한다.
//즉 x===y이다.
//이는 x와 y가 바라보는(참조하는) 값이 같기 때문에 이런현상이 나타난 것이다.
//x 배열이 참조하는 값의 데이터만을 복제해 y에 할당할 수는 없을까?
//그렇게 될 수만 있다면 y를 변형시켜도 x에 영향을 미치지 않게 될 것이다.
위에 대한 이해를 바탕으로 Shallow Copy와 Deep Copy에 대해 알아보도록 한다.
이를 설명하기 위해 아래에 소개된 메소드들은 하나의 예시일 뿐이다. Shallow Copy나 Deep Copy는 하나의 개념일 뿐, 이를 구현 하는 방식은 다양할 수 있다.
말 그대로 얕게 복제하는 것을 의미한다.
let arr1 = [[1],2];
let arr2 = Object.assign([], arr1) //arr1 배열을 복사
//arr1을 단순히 arr2에 할당하는게 아니라,
//Object.assign() 메소드를 이용해 arr1의 데이터를 복사해 arr2에 할당해 주었다.
console.log(arr1 === arr2) //false
//값이 false가 나오는 것을 보니
//arr1과 arr2가 참조하는 값이 다른 모양이다.
//따라서 이제 arr2에 변형을 가해도 arr1에는 어떠한 영향도 주지 않게 된다.
//이 방식은 배열이나 객체를 변수에 단순할당했을 때의 문제점을 모두 해결해주었을까?
//아쉽게도 그렇지는 않다.
console.log(arr1[0] === arr2[0]) //true
//값이 true가 나왔다.
//즉 arr1[0] 배열과 arr2[0] 배열의 참조 값이 같다는 것이다.
//Objecet.assign()메소드의 경우
//새로운 객체에 원복 객체의 프로퍼티의 값을 정확히 복사한다.
//하지만 만약 프로퍼티의 값이 객체(배열) 형태라면, 객체의 참조를 복사한다.
//따라서 얕은 깊이에서 복제는 작동하지만,
//완벽한 복제는 아니라서 좀 더 깊이 들어가면 같은 참조 값을 공유하는 현상이 발생한다.
//이런 식의 Copy를 Shallow Copy라고 한다.
Shallow Copy와는 다르게 모든 깊이에서 복제하는 것을 의미한다.
let arr1 = [[1],2];
let arr2 = JSON.parse(JSON.stringify(arr1));
//우선 JSON.stringify() 메소드를 이용해
//JavaScript 객체를 JSON 문자열로 변형시켜준다.
//이제 arr1의 참조는 사라지고,
//arr1의 데이터는 JSON 문자열 형식으로 변환된다.
//JSON.parse()메소드를 이용해
//JSON 문자열을 다시 JavaScript에 해당하는 객체로 변환한다.
//그 객체가 arr2에 할당된다.
console.log(arr1 === arr2) //false
console.log(arr1[0] === arr2[0]) //false
//모든 깊이에서의 복제가 이루어졌다.
//이런 식의 Copy를 Deep Copy라고 한다.