재귀 함수를 써보자

GDana
gdana
Published in
4 min readAug 25, 2019

뭐든 직접 경험해봐야 안다고, 재귀의 개념은 알지만 막상 써보려하니 제대로 알고 있지 않아 공부한 재귀에 대해 기록해보겠습니다.

재귀란

함수가 자기 자신을 호출하는 행위를 재귀 함수라고 하며 내부적으로 자기 자신을 호출하면 특정 문제를 해결할 수가 있습니다.

간단한 예제

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 해줍니다.

재귀 호출은 사람에게는 가독성을 높여주지만 컴퓨터에게는 많은 부담을 주기 때문에 재귀로 간단하게 해결할 수 있는 문제일 경우 사용하는 것이 좋다고 합니다. 그에 걸맞게 재귀로 풀어내고자 했던 문제를 제대로 푼 것일지 모르겠지만 다음번에 사용할 땐 조금 더 친근하게 다가올 수 있길 바래봅니다.

--

--