(JS) document.getElementsByClassName(className)을 재귀함수로 구현

호두파파·2021년 2월 1일
0

(JS) 함수

목록 보기
8/10

재귀란

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

function fact(n) {
  if (n <= 1) {
    return 1;
  }
  return n*fact(n-1);
}

위 예제는 n의 값으로 숫자 5가 주어졌을때, 54321=120 의 값이 반환되는 함수로 재귀의 대표적인 특성을 뽑을 수있다.

  1. 종료 : false의 값이 들어오면 멈춰야 한다.
    n의 값이 1보다 작을 경우 멈추는 조건을 추가해줘야 한다.
    if(n <= 1)

  2. 실행 : true의 값이 들어오면 재귀를 호출한다.
    n의 값이 1보다 큰 'if(n <= 1)'의 false가 되는 구문이 실행된다. 해당 구문이 실행되는 조건은 n이 1이 되어 if의 값을 만족할때까지 실행된다.

  3. 재귀 : 자기 자신을 호출해 특정 문제를 해결한다.
    2번이 if문을 만족할때까지 계속 실행될 수 있기 때문에
    반복문을 사용하지 않고 자기 자신을 호출함으로써 조건문이 만족할때까지 실행된다.


<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을 구현하는 것을 목표로하는 재귀 함수를 구현해보자


<구현해야할 문제>

특정 class의 이름이 속한 요소들을 가져오고, 가져온 모든 요소들을 배열로 묶어서 리턴하라.
(즉, document.getElementsByClassName(className)와 같은 작동을 하는 함수를 구현하는 것이다.)

<알고리즘>

  • HTML의 에 속한 element(요소)를 하나씩 선택한다.
  • 선택한 element가 class가 있고, 그 class가 className에 포함하면,
    새로 만든 배열에 추가한다.
  • 또한, 그 선택한 element가 child Node(자식 Node)가 있는 지 확인한다.
  • 만약 있다면, 그 childNode도 class가 있고, 그 class가 className에 포함하는지 확인한다.(재귀함수 사용)
  • 포함이 되어 있다면, 새로 만든 배열에 추가한다.
  • element내에 또 다른 element도 className에 포함하는 class가 있다면, 그 element들을 가져와 배열에 추가하는 방식으로 진행한다.

<구현>

1) HTML의 와 빈 배열을 선언한다.

var bodyHtml = document.body; // <body>
var bin = [];

2) 재귀함수로 돌릴 함수를 선언한다.

var check = function(bodyHtml) {

}

3) 선택한 element가 class가 있고, 그 class가 className에 포함하면, 새로운 배열에 추가한다.

var check = function(bodyHtml) {
// 특정 클래스 값을 제어하기 위해  classList 사용

if(bodyHtml.classList && 
bodyHtml.classList.contains(className)) {
bin.push(bodyHtml); // 새로 만든 배열에 추가 
}

4) 또한, 그 선택한 element가 childNode(자식 Node)가 있는지 없는지 확인한다.

만약 있다면, 그 child Node를 재귀함수로 돌려, 위에서 했던 방식으로 element를 체크한다.

//'hasChildNodes()' 메소드를 사용해서,
// 선택한 element가 child Node(자식 Node) 있는지 확인

if(bodyHtml.hasChildNodes()) {
// 자식 Node가 있다면, 각 자식 Node를 하나씩 빼서
	for (let i = 0; i < bodyHtml.childNodes.length; i++) {
	// 재귀 함수에 돌려서 특정 클래스 값이 있는지 확인
		check(bodyHtml.childNodes[i]);
   }
 }

5) 선택한 element가 className에 포함되어서, 추가된 최종 배열을 리턴한다.

check(bodyHtml); // 재귀함수를 처음에 돌리기 위해, 재귀함수를 호출한다.
return bin; // element들이 추가된 배열을 리턴한다.

소스코드

const getElementByClassName = function(className) {
    const bodyHtml = document.body;
    const bin = [];
    let check = function(bodyHtml) {
        if (bodyHtml.classList && bodyHtml.classList.contains(className)) {
            bin.push(bodyHtml);
        }
        if (bodyHtml.hasChildNodes()) {
            for(let i = 0; i < bodyHtml.childNodes.length; i++) {
                check(bodyHtml.childNodes[i]);
            }
        }
    }
    check(bodyHtml);
    return bin;
}

위 소스코드는 재귀함수를 사용하기 위해 함수안에 (재귀) 함수를 사용했다. 사용된 함수를 호출하기 위해, 처음 document.body(bodyHtml)를 호출해서, 함수를 돌리고, 각 요소와 각 요소들의 각 자식 Node를 체크하면서 className에 속하는 class를 가진 요소들을 불러오고,

그 불러온 요소들을 배열에 추가하여, 최종적으로 배열을 리턴하는 함수를 구현했다.

profile
안녕하세요 주니어 프론트엔드 개발자 양윤성입니다.

0개의 댓글