[구현] document.getElementsByClassName(className)을 재귀함수로 구현하기

in kr-dev •  7 years ago  (edited)

getElementsByClassName(className)은 class의 이름을 이용해서 HTML 요소(element)들을 가져오는 메소드이다.

아래와 같은 html이 있다고 해보자.

<!DOCTYPE html>
<html>
<body>
<div class=“numberOne”>First div element.</div>
<div class=“numberOne”>Second div element.</div>
<button onclick=“myFunction()”>Try it</button>
<script>
function myFunction() {
var x = document.getElementsByClassName(“numberOne”);
x[0].innerHTML = “changed div class”;
}
</script>
</body>
</html>


위 html은 “Try it” 버튼을 클릭했을 때, 자바스크립트에 있는 함수가 작동하는데,

자바스크립트에서 var x = document.getElementsByClassName(“numberOne”);는

“numberOne” 이름의 class를 가지고 있는 요소들을 가져온 것을 변수 x라고 선언했다.

그리고 변수 x중 첫번째 값(x[0])의 내용을 “changed div class”로 바꾸라고 작성했다.

그러면, 위 html에서 x중 첫번째 값은<div class=“numberOne”>First div element.</div> 이고,

이 요소에서 “First div element.”가 “changed div class”로 바뀌게 된다.

위와 같이, class 이름을 사용해서 요소들을 가져올 수 있다.


<구현해야할 문제>

특정 class의 이름이 속한 요소들을 가져오고, 가져온 모든 요소들을 배열로 묶어서 리턴하라.

(즉, document.getElementsByClassName(className)와 같은 작동을 하는 함수를 구현하는 것이다.)


<알고리즘>

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


<구현>

이제, document.getElementsByClassName(className)을 직접 구현해보자.


<1> HTML의 <body>와 빈 배열을 선언한다.

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


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

var hasClass = function(bodyHtml) {
}


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

var hasClass = function(bodyHtml) {
// 특정 클래스 값을 제어하기 위해 classList 사용
if(bodyHtml.classList && bodyHtml.classList.contains(className)) {
result.push(bodyHtml); // 새로 만든 배열에 추가
}


<4> 또한, 그 선택한 element가 Child Node(자식 Node)가 있는지 없는지 확인한다.
만약 있다면, 그 Child Node를 재귀함수로 돌려, 위에서 했던 방식으로 element를 체크한다.

// 'hasChildNodes()' 메소드 사용해서,
// 선택한 element가 Child Node(자식 Node) 있는지 확인
if(bodyHtml.hasChildNodes()) {
// 자식 Node가 있다면, 각 자식 Node를 하나씩 빼서
for(var i = 0; i< bodyHtml.childNodes.length; i++) { 
// 재귀함수에 돌려서 특정 클래스 값이 있는지 확인
hasClass(bodyHtml.childNodes[i]); 
}
}


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

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


<소스코드>

var getElementsByClassName = function(className
){
var bodyHtml = document.body; 
var result = []
var hasClass = function(bodyHtml) {
if(bodyHtml.classList && bodyHtml.classList.contains(className)) {
result.push(bodyHtml);
}
if(bodyHtml.hasChildNodes()) {
for(var i = 0; i< bodyHtml.childNodes.length; i++) {
hasClass(bodyHtml.childNodes[i]);
}
}
}
hasClass(bodyHtml);
return result;
};


위 소스코드는 재귀함수를 사용하기 위해 함수안에 (재귀) 함수를 사용했다.

사용된 함수를 호출하기 위해, 처음에는 document.body(bodyHtml)를 호출해서, 

함수를 돌리고,각 요소와 각 요소들의 각 자식 Node를 체크하면서 className에 속하는 

class를 가진 요소들을 불러오고, 그 불러온 요소들을 배열에 추가하여, 

최종적으로 배열을 리턴하는 함수를 구현했다.

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!