본문 바로가기

T.I.L

23-05-24 T.I.L 깊은 복사 알고리즘

문제 설명

얕은 복사와 깊은 복사를 공부하고 있었다. 얕은 복사가 어떤 방식으로 객체를 카피 하는지 이해했고 이를 방지하기 위해서 깊은 복사로 불리는 함수를 이용해야 한다는 것도 이해했다.

var copyObjectDeep = function(target) {
	var result = {};
	if (typeof target === 'object' && target !== null) {
		for (var prop in target) {
			result[prop] = copyObjectDeep(target[prop]);
		}
	} else {
		result = target;
	}
	return result;
}

위의 함수가 깊은 복사 함수의 알고리즘이다.

이 알고리즘이 어떻게 깊은 복사를 이뤄내는지 감이 잡히지 않았다.

시도

일단 한 줄씩 천천히 읽어내려갔다. 

var copyObjectDeep = function(target) 첫줄, 식별자copyObjectDeep에 함수를 변수로 할당했다. 함수의 매개변수는 target이다. 다행히 콜백함수는 아니다. 두번째 줄 부터 함수의 알고리즘이 시작된다.

var result = {}; 우선 식별자  result에 빈 객체 {} 를 할당했다. 

if (typeof target === 'object' && target !== null) 그리고 if문에 조건을 걸었다.  첫 번째typeof target === 'object' 이는 함수의 매개변수가 객체여야 한다는 뜻, 두 번째 조건은 target !== null 그리고 빈 값이 아니어여 한다는 것. && 그리고 논리 연산자 곱. 두 조건이 모두 참일 때 if문이 발동한다.

 

for (var prop in target), if문이 참일때 for in 문이 발동된다. for in 문은 객체의 속성을 출력한다. target은 무조건 객체일 것이니 target의 객체의 속성이 prop에 할당된다.

 

result[prop] = copyObjectDeep(target[prop]) 그리고 이곳

result는 객체다. 즉 result의 [prop] 값은 =copyObjectDeep(target[prop]) 이것과 똑 같다고 할 수있다. 

 

copyObjectDeep()은 지금의 알고리즘이 행해지는 함수다. 즉 자신 알고리즘으로 진행되는 과정에서 또 자신의 알고리즘이 진행이 되는 재귀 함수다.

 

target[prop] 이건. 일단 prop는 target의 객체의 속성이다. 즉 target의 값이 copyObjectDeep()의 매개변수로 작동이 된다는 뜻이다.

 

여기까지 코드리딩을 진행했지만 더 이상은 현재 내 수준의 직관으로는 해독하기 힘들었다. 그래서 vs코드를 통해서 좀 더 자세히 알아봐야 겠다. console.log를 통해

해결

var obj = {
	a: 1,
	b: {
		c: null,
		d: [1, 2],
	}
};
var obj2 = copyObjectDeep(obj);

obj2.a = 3;
obj2.b.c = 4;
obj2.b.d[1] = 3;

객체를 만들고 함수 속에 console.log()를 넣어서 어떤 데이터가 들어가는지 알아보자!

for (var prop in target) {
			result[prop] = copyObjectDeep(target[prop]);
            console.log(target[prop])
		}

함수의 알고리즘에 이해가 안가는 부분을 찍어보았다.

1, null, 1, 2, [ 1, 2 ], { c: null, d: [ 1, 2 ] } 가 나왔다. target 즉 obj의 요소가 말 그대로 전부 함수의 매개변수로 작용한다는 뜻이다. 천천히 생각하자, 우선 1, 1은 a 키의 값이다. 1이 copyObjectDeep() 함수를 돌면 if의 조건에 해당하지 않기 때문에 else {result = target;} 으로 간다. 

 

잊지 말아야 할 것ㅡ 지금 이 결과는 재귀함수였다. 즉 result[prop]=1 이라는 것,  result[a]=1 이라는 것, a키의 값이 1이라할당 한다는 뜻이다.!

 

result[prop] = copyObjectDeep(target[prop]);는 키값을 다시 할당하는 역할을 하고 있다는 의미다.

객체부분을 정리하면

 result[b]= copyObjectDeep({c: null,d: [1, 2],})

copyObjectDeep({c: null,d: [1, 2],})=function(target)  //재귀함수// 

copyObjectDeep(b)=function({c: null,d: [1, 2],})         //재귀함수//  그리고 또 다시

copyObjectDeep(c)=function(null)                             //재귀함수의 재귀함수//

copyObjectDeep(d)=function([1, 2])                          //재귀함수의 재귀함수//

 

obj2의 요소를 전부 다 재 할당을 해주고 있다!

그래서 obj와 obj2와 겉 모습은 똑 같지만 다른 데이터 주소를 가지고 있다고 볼 수 있다. 그래서 obj2 나 obj의 요소에 대한 값을 재 할당해도 같이 바뀌는 일이 없다.

 

알게된 점

깊은 복사가 어떤 알고리즘을 통해서 성사되는지 알 수 있었다.(모든 요소의 재 할당) 

깊은 복사의 알고리즘을 이해했다.

for in의 객체요소의 반복에 대해서 더 잘 이해할 수 있었다.