재귀란
함수가 자기 자신을 호출하는 행위를 재귀 함수라고 하며 내부적으로 자기 자신을 호출하면 특정 문제를 해결할 수가 있습니다.
간단한 예제
function fact(n){if(n <= 1){return 1;}return n * fact(n-1);}
위의 예제는 n의 값으로 숫자 5가 주어졌을 때, `5*4*3*2*1=120`의 값이 반환되는 함수로 예제로 재귀의 대표적인 특성을 뽑을 수 있습니다.
1. 종료 : false의 값이 들어오면 멈춰야 한다.
n의 값이 1보다 작은 `if(n <= 1)` true일 경우 fact()는 멈추게 된다.
2. 실행 : true의 값이 들어오면 재귀를 호출 한다.
n의 값이 1보다 큰 `if(n <= 1)`의 false가 되는 구문이 실행된다. 해당 구문이 실행되는 조건은 n이 1이 되어 if의 값을 만족할 때까지 실행된다.
3. 재귀 : 자기 자신을 호출하여 특정 문제를 해결한다.
2번이 if문을 만족할때 까지 계속 실행될 수 있는 이유로 `for(let i = 0; i <= n; i++)` 반복문을 사용하지 않고 자기 자신을 호출함으로써 `if`와 `else`를 만족할 때까지 실행되게 된다.
재귀로 풀어내고자 했던 문제
<p class=”targetClassName”></p><p><p class=”targetClassName”></p></p><p><div class=”somediv”><div class=”innerdiv”><span class=”targetClassName”>hi</span></div></div></p>
위와같이 마크업되어 있을때 targetClassName
클래스 이름을 가진 노드를 반환하는 document.getElementsByClassName
를 구현하는 것이 목표로 완성된 예제를 먼저 확인해 봅니다.
1. 종료
function getElementsByClassName(className) {let result = [];let el = document.body;function chk(el){…}chk(el)return result;};
구현된 재귀 함수는 내부 함수로 구현했기 때문에 재귀가 종료되어 반환되는 값으로는 `getElementsByClassName()` 함수에서 return되는 `result`가 됩니다.
2. 실행
function chk(el){if(el.classList && el.classList.contains(className)){result.push(el)}if(el.hasChildNodes()){for(var i = 0; i< el.childNodes.length; i++) {chk(el.childNodes[i]);}}}
chk() 재귀 함수는 기대하는 값이 없을 때까지 chk()를 실행합니다.
3. 재귀
if(el.hasChildNodes()){for(var i = 0; i< el.childNodes.length; i++) {chk(el.childNodes[i]);}}
document.body에 자식노드가 있다면 자식노드 길이만큼 반복문을 실행하는 if문의 `chk(body.childNodes[i])`를 실행함으로써 재귀 함수를 호출합니다. 그리고 인자로 들어간 자식노드는 아래와 같겠죠!
<body>…</body><p></p><p></p><div class=”somediv”>…</div><div class=”innerdiv”>…</div><span class=”targetClassName”>hi</span>if(el.classList && el.classList.contains(className)){result.push(el)}if(el.hasChildNodes()){for(var i = 0; i< el.childNodes.length; i++) {chk(el.childNodes[i]);}}
chk() 인자로 들어간 자식노드에 className
이 있다면 result에 인자로 들어온 값을 push 해주고 나머지 document.body.childNodes
도 모두 확인합니다. 그리고 더이상 className을 가진 classList가 없다면 return result
해줍니다.
재귀 호출은 사람에게는 가독성을 높여주지만 컴퓨터에게는 많은 부담을 주기 때문에 재귀로 간단하게 해결할 수 있는 문제일 경우 사용하는 것이 좋다고 합니다. 그에 걸맞게 재귀로 풀어내고자 했던 문제를 제대로 푼 것일지 모르겠지만 다음번에 사용할 땐 조금 더 친근하게 다가올 수 있길 바래봅니다.