깊은 복사 관련되서 객체나 배열은 원시값이 아닌 call by reference 방식으로 데이터가 저장되기 때문에
아래와 같은 결과가 나오게 된다.
const obj = { name : 'lee', age: 20} ;
const obj2 = obj;
const obj3 = {name: 'lee', age: 20};
console.log(obj === obj2) // true;
console.log(obj === obj3) // false;
그래서 obj를 복사하기 위해서는 얕은 복사와 깊은 복사 개념이 있는데 이 중에서 깊은 복사와 관련된 내용에 대해서 "최00"님께서 고민하신 내용에 대해서 흥미로워서 글을 남긴다. 이 자릴 빌어서 다시 한번 감사하다는 말씀 올리겠습니다. 😍
깊은 복사를 하는 방법으로 아래와 같은 함수 deepCopy를 사용해서 선언을 했는데
이 객체 내에 배열이 있을 경우 배열로 나오는 것이 아닌 객체의 형태로 원하지 않은 값이 나온다는게 문제였다.
var obj = {
name: 'Choi',
age: 30,
obj2: {
name: 'Shin',
age: 27,
obj3: {
name: '애기',
age: 1,
},
},
arr: [1, 2, 3, 4, 5],
};
function deepCopy(obj) {
var copy = {};
for (let value in obj) {
copy[value] = obj[value];
if (typeof copy[value] === 'object') {
copy[value] = deepCopy(obj[value]);
}
}
return copy;
}
const a = deepCopy(obj);
console.log(a);
// a의 실행 결과
{
name: 'Choi',
age: 30,
obj2: { name: 'Shin', age: 27, obj3: { name: '애기', age: 1 } },
arr: { '0': 1, '1': 2, '2': 3, '3': 4, '4': 5 }
}
위와 같은 이유로 a.arr의 내용이 마치 객체처럼 표시되는 것이다.
현재 키 값이 객체일 경우 그것이 배열인지 혹은 배열이 아닌지를 확인을 해야 한다.
배열의 기본적인 조건은 length와 각 인덱스가 key 값으로 들어갈 수 있다라는 점이다.
이를 기준으로 객체와 배열을 구분해 내고, 만약 배열의 경우 copy = {}이 아닌 copy = []를 사용하여 배열을 반환하게 끔 하였다.
추가적으로 배열 안에도 똑같이 객체나 배열이 있을 경우 이를 재귀적으로 처리할 수 있도록 구현하였다.
var obj = {
name: 'Choi',
age: 30,
obj2: {
name: 'Shin',
age: 27,
obj3: {
name: '애기',
age: 1,
},
},
arr: [{ name: 'lee' }, { name: 'jin', arr: [1, 2, 3, 4, 5] }, 3, 4, 5],
};
const MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
const isArrayLike = function (list) {
const length = list === null ? null : list.length;
return typeof length === 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
};
function deepCopy(obj) {
if (isArrayLike(obj)) {
// 배열의 경우
const copy = [];
for (let i = 0; i < obj.length; i++) {
if (typeof obj[i] === 'object') copy.push(deepCopy(obj[i]));
else copy.push(obj[i]);
}
return copy;
}
var copy = {};
for (let key in obj) {
if (typeof obj[key] === 'object') {
copy[key] = deepCopy(obj[key]);
} else {
copy[key] = obj[key];
}
}
return copy;
}
const a = deepCopy(obj);
console.log(a.arr === obj.arr); // false
console.log(a.arr[0] === obj.arr[0]); // false
console.log(a.arr[1].arr === obj.arr[1].arr); // false