웹브라우저 JavaScript

노드 종류 API

노드 작업을 하게 되면 현재 선택된 노드가 어떤 타입인지를 판단해야 하는 경우가 있다. 이런 경우에 사용할 수 있는 API가 nodeType, nodeName이다. 

  • Node.nodeType
    node의 타입을 의미한다. 
  • Node.nodeName
    node의 이름 (태그명을 의미한다.)

Node Type

노드의 종류에 따라서 정해진 상수가 존재한다. 아래는 모든 노드의 종류와 종류에 따른 값을 출력하는 예제다.

for(var name in Node){
   console.log(name, Node[name]);
}

결과

ELEMENT_NODE 1 
ATTRIBUTE_NODE 2 
TEXT_NODE 3 
CDATA_SECTION_NODE 4 
ENTITY_REFERENCE_NODE 5 
ENTITY_NODE 6 
PROCESSING_INSTRUCTION_NODE 7 
COMMENT_NODE 8 
DOCUMENT_NODE 9 
DOCUMENT_TYPE_NODE 10 
DOCUMENT_FRAGMENT_NODE 11 
NOTATION_NODE 12 
DOCUMENT_POSITION_DISCONNECTED 1 
DOCUMENT_POSITION_PRECEDING 2 
DOCUMENT_POSITION_FOLLOWING 4 
DOCUMENT_POSITION_CONTAINS 8 
DOCUMENT_POSITION_CONTAINED_BY 16 
DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC 32

아래 예제는 노드 종류 API를 이용해서 노드를 처리하는 예제다. 함수가 자기 자신을 호출하는 것을 재귀함수라고 하는데 본 예제는 재귀 함수의 예를 보여준다.

 

<!DOCTYPE html>
<html>
<body id="start">
<ul>
    <li><a href="./532">html</a></li> 
    <li><a href="./533">css</a></li>
    <li><a href="./534">JavaScript</a>
        <ul>
            <li><a href="./535">JavaScript Core</a></li>
            <li><a href="./536">DOM</a></li>
            <li><a href="./537">BOM</a></li>
        </ul>
    </li>
</ul>
<script>
function traverse(target, callback){
    if(target.nodeType === 1){
		//if(target.nodeName === 'A')
		callback(target);
		var c = target.childNodes;
		for(var i=0; i<c.length; i++){
			traverse(c[i], callback);		
		}	
	}
}
traverse(document.getElementById('start'), function(elem){
	console.log(elem);
});
</script>
</body>
</html>

 

댓글

댓글 본문
  1. 싸알
    완료~
  2. 이준호
    완료
  3. 완료
  4. 여러분 위 코드는 C에서와 같은 일반적인 재귀함수의 탈출 조건이 필요 없습니다.
    반복은 재귀함수에서 제어하지 않고, for문에서 c.length로 c를 받는 순간 정해집니다

    body태그의 child node1를 탐색...
    child node1의 child node2를 탐색... (body의 child node 전부 할때까지 반복)
    C언어 였다면 child 노드가 아닌 것은 조건문으로 메모리가 null이면 탈출했겠지만

    여기선 이미 구현되어 있는 var c=target.childNodes; 을 이용할 때
    이부분이 이미 정상적인 child node의 메모리를 보장하기 때문이에요.

    C 였다면 if (c == null) return; 이런 식의 조건이 있어야만 하지만,
    여기서는 이게 API니까, childNodes의 메모리가 절대로 null(정의되지않음)이 아닌거죠.

    너무 생소하시면 일단 이것만 기억하세요.
    이 API(childNodes)가 정상적인 child의 메모리를 찾아주지 않으면 존재 의미가 없겠지요.
    덕분에 우리는 그런 예외들을 고려하지 않거나, 덜하고 코딩 할 수 있어요.
    대화보기
    • 정승옥
      완료
    • 김진욱
      완료
    • function traverse() {
      var queue = new Array();
      queue.unshift(document.getElementById('start'));

      while(queue.length > 0){
      var top = queue.pop();
      console.log(top.nodeName);

      if(top.childNodes.length > 0) {
      for (var i = 0; i < top.childNodes.length; i++) {
      queue.unshift(top.childNodes[i]);
      }
      }
      }
      }
      traverse();
    • 준바이
      조금 더 첨언을 하자면 저는 basecase의 의미를 세우는 코드로 리버전하자면 코드 제일 윗줄에

      if(target.nodeType !== 1) {
      // base case
      return null;
      }

      로 잡아주면 좋을 것 같습니다. 재귀관련 예시 코드들 보면 탈출 조건을 최대한 빨리, 가독성 좋게 표현하는 것 처럼 보이기 때문입니다.
      대화보기
      • ㄴㅇ
        매개변수(parameter) 는 함수에 입력되는 값(input) 이라고 생각하시면 됩니다.
        함수는 이 값을 받아서 이리저리 가공을 한 후 결과(output) 를 뱉어내죠.
        대화보기
        • 매개변수......가 뭐지.....................
        • 생존코딩
          자식노드를 계속 탐색하다보면 언젠간 Element가 아닌 노드가 target 파라미터에 들어가게 됩니다(텍스트 노드가 target 파라미터에 들어가겠죠?). 그러면 if(target.nodeType === 1) 조건문을 건너뛰고 함수가 그대로 종료되면서 더 이상 callback함수를 호출하지않습니다.
          대화보기
          • ㅈㄱㅎㅅ
            재귀함수는 무한반복을 막기 위해 자신을 정지시키는 코드가(base case) 꼭 들어가야된다고 하던데 여기에서 그 부분은 어딘가요?

            function traverse(target, callback){
            if(target.nodeType === 1){
            //if(target.nodeName === 'A')
            callback(target);
            var c = target.childNodes;
            for(var i=0; i<c.length; i++){
            traverse(c[i], callback);
            }
            }
            }
          • 굼벵이
            완료
          • 모든일이일사천리
            Done : 19/11/24 3PM
          • 정홍
            완료
          • 2019-10-15 8:35pm 완료
          • 재귀함수 코드 관련하여 보충 설명 해주실 수 없나요. 이전 기본 자바스크립트 수업에서의 callback 예제랑 동떨어진 것처럼 느껴져서 .. 이해가 잘 안되요.
          • 지나가는 나그네
            A,B,C로 간단히 말씀드릴게요

            A가 B 호출
            A 잠깐 대기
            B가 C 호출
            B 잠깐 대기
            C에서 탈출조건 성립 되돌아간다.
            B 다시 재개(재귀함수 밑 부분 코드 실행)
            A 다시 재개 (재귀함수 밑 부분 코드 실행)

            이것을 1~100개 까지 있다고 친다면
            일단 100까지 쭉 갑니다(100이 최초 탈출조건 성립이라 가정시)
            탈출 조건이 성립되면 이제 다시 100~1까지 나머지 코드들을 실행하면서 돌아옵니다.

            자료구조를 공부하시면 넓은 관점에서 보실수 있을거에요
            대화보기
            • 훈민정
              재귀함수 보충 수업 부탁드립니다. 다른건 다 이해했는데 재귀함수는 도저히 이해가 안돼네요..
            • GOD IS ALWAYS GOOD
              밑에 계신 분이랑 똑같은 질문인데요 ㅠㅠ

              처음 start 의 childNodes에 대한 for문이 돌면서 traverse가 그 안에서 실행되는데

              그럼 다시 또 그 childNodes에 대한 childNodes를 가져와서 for를 돌리고(아직 start는 첫번째 자식밖에 돌지 못한상태) 그 childNode가 또 childNode 또돌리고

              1~5 까지 있다고 한다면

              1
              12

              2
              23

              3
              34

              4
              45

              5

              345

              2345

              1
              12
              123

              34

              45

              5
              ....

              뭐 이런식이 아닌가요???ㅜㅜㅜ
            • 이채
              알림이 떠서 들어와봤는데 3주쯤 지났다고 벌써 기억이 잘 안 나네요..ㅎㅎㅎㅎ
              제 능력 부족으로 완전히 이해했다고 선뜻 대답하긴 어렵지만ㅠ.ㅠ많은 도움이 되었습니다 감사합니다^^
              대화보기
              • 재귀함수
                1. target을 출력하고, target의 childNodes에 대해서 for문을 돌며 다시 traverse 구문을 수행합니다.
                childeNodes의 childeNodes를 돌면서 결국 전체 엘리멘트를 검색합니다.

                2. 조건문의 대상으로 callback 한줄만 거는 이유는, 전체 엘리멘트의 탐색을 위해서입니다.
                (target이 A태그가 아니면 출력은 하지 않지만, 자식에 A태그가 있다면, 탐색해야 하기 때문에 출력에만 조건을 겁니다.)

                3. A태그 조건문의 범위를 끝까지 걸었을 때,
                - 첫번째 target은 body인데 A가 아니므로 출력하지 않습니다.
                - 원래대로라면 출력만 하지 않고, 밑의 for문을 돌며 body의 childNodes를 다시 검사합니다.
                하지만, 조건문의 범위로 인해 탐색도 안하고 종료됩니다.
                - 결과적으로 아무것도 출력되지 않습니다.
                대화보기
                • 이채
                  var c = target.childNodes;
                  for(var i=0; i<c.length; i++){
                  traverse(c[i], callback);
                  }
                  이 부분에서 for문을 반복하면 c[0], c[1], c[2]... 이런 식으로 body 바로 아래의 자식노드만 나오는 것은 아닌건가요?
                  콘솔에서 start.childNodes를 치면 [text, ul, text, script, text] 이렇게만 나오더라구요.
                  traverse에 넣었기 때문에 다시 c로 돌아가서 다시 childNodes의 childNodes가 되는 것인지.. 개념이 안 잡히다 보니 돌려봐도 헷갈립니다ㅠㅠ

                  또 주석처리한
                  //if(target.nodeName === 'A')
                  callback(target);
                  이 부분에서 A태그만 선택하는 것은 callback(target) 한줄만인 이유가 무엇인지 이해가 잘 안 갑니다.

                  function traverse(target, callback){
                  if(target.nodeType === 1){
                  //if(target.nodeName === 'A') {
                  callback(target);
                  var c = target.childNodes;
                  for(var i=0; i<c.length; i++){
                  traverse(c[i], callback); }
                  }
                  }
                  }
                  이런 식으로 A태그 부분을 끝까지 묶어버리니 아무 태그도 뜨질 않네요.
                  처음 nodeType === 1 이 부분은 끝까지 묶어서 작동시키는데, A태그만 분류할 때는 한 줄만 실행하는게 어떤 점에서 차이가 있는건지, 댓글을 읽어봐도 완전히 와닿지가 않습니다ㅠ.ㅠ고수분들 도와주세요
                • 성기훈
                  body태그와 ul태그 사이에 줄바꿈이 들어가 있어서 그렇습니다.
                  body태그와 ul태그 사이에 띄어쓰기든 줄바꿈이든 공백이 들어가게 되면 그걸 글자로 인식해서 #text라고 나타내고
                  실제로 body태그와 ul태그를 딱 붙여주면 공백이 없게 되어 #text가 사라질 겁니다.
                  우리는 편의상 줄바꿈을 넣지만 Node는 공백도 자식노드로 인식하여 #text값이 나오는 거지요.
                  대화보기
                  • 흑흑
                    1번 영상에서

                    body 태그의 첫번 째 차일드가 왜 text 인지 이해가 안됩니다.......

                    혹시 아시는분???
                  • JuicyFresh
                    감사합니다.
                  • 공부중
                    if문 바로 다음 한 줄 코드는 암시적으로 if문의 내용이라고 판단하여 중괄호 생략 가능합니다. 두 줄 부터 중괄호를 쳐서 if문 안의 내용이라는 것을 명시해줘야 하구요. for문, while문도 마찬가지 입니다.
                    대화보기
                    • 김수
                      callback....0901...
                      너무어려우 ㅓㅠㅠ히잏ㅇ
                    • 생선과고양이
                      20140426 3번 돌려봐도 이해가 안가서 이번강의는 패스 합니다
                    • 인자
                      function traverse(target, callback){
                      if(target.nodeType === 1){
                      if(target.nodeName === 'A')
                      callback(target);
                      var c = target.childNodes;
                      for(var i=0; i<c.length; i++){
                      traverse(c[i], callback);
                      }
                      }
                      }
                      여기서 if(target.nodeName === 'A') 뒤 중괄호가 생략되있는데 댓글들 보면서 생각해봤습니다. 중괄호를

                      function traverse(target, callback){
                      if(target.nodeType === 1){
                      if(target.nodeName === 'A'){
                      callback(target);
                      var c = target.childNodes;
                      for(var i=0; i<c.length; i++){
                      traverse(c[i], callback);
                      }
                      }
                      }
                      }
                      이런식으로 밑에 for문까지해버리게되면 body태그에서 child노드가 a인것을 찾고 그 child노드, 즉 a태그안에 있는 childnode를 찾아 나가는거기때문에 body태그 바로밑에 a태그가 childnode로 없기때문에 결과가 아무것도 안나오는 것 같습니다. body-ul-li-a이런식으로 거쳐서 나중에 나오기때문이죠.
                    • 인자
                      if(target.nodeName === 'A')
                      callback(target);
                      여기서 중괄호 묶어 줘야 하지 않나요?
                      if(target.nodeName === 'A'){
                      callback(target);
                      }
                      이런식으로요.
                    • 박인호
                      12-29
                      수강완료.
                      재귀함수가 처음봤을때 이해가 잘 안 됐었는데
                      보다보니 어떻게 돌아가는 녀석인지 알겠네요.
                      감사합니다.
                    • 도레미
                      이번 내용 좀 어려웠지만,, 다음에 복습하러 다시 올게요!
                      그치만 이번 강의 방식 너무 중요하고 감사해요!... 실무에서,, 어떻게 코드를 작성할 것인가하는 생각을 같이 따라갈 수 있어서요!
                    • 박민경
                      조건문에서 {}이렇게 묶지 않은 두번째는 묶어주면 콘솔창에 아무것도 안뜨는데 이유가 뭔가요?
                      언제 묶어야 하고 언제 안묶어요 되는 건가요?
                    • Byungsoo Kim
                      감사합니다.
                    • 수복
                      다시 봐야겠군요...
                    • Jeffry
                      @enqn192 음 저도 javascript는 배운지 1달이 안되었지만 재귀에 대해서는 설명드릴수 있어서 짧은 지식으로 글써봅니다. 님이 말씀하시는거는 2중for문 하고 비슷한데 밖에 for문의 증감자가 하나 증가할 때마다 안의 for문이 돌게 되면 말하신것 처럼 나오는데 지금 저거는 재귀함수라서 body안에 들어와서 ul들어가고 li들어가서 안에 더이상 들어갈 곳이 없으면 return return 해서 쭉쭉 나오고 ul까지 나왔으면 다시 밑에 ul가서 또 들어가고 들어가고 그렇게 반복해서 더이상 들어갈곳 없이 밑에까지 내려오면 마지막으로 return해주게 되면 저렇게 다 출력이 됩니다! 어려운데 tree처럼 하나 끝까지 들어가서 다시 나오고 한다고 생각하시면 될 것 같아요!
                    • Seo Yun Seok Tudoistube
                      자바스크립트 수업에서 재귀함수 보다가 일루 왔는데, Node.js 강의 들을때 한번 더 들어야 겠습니다.
                      암기하지 않고 사용법을 익히면서 이해할 수 있는 빠른 방법을 찾고 싶습니다^^;;;
                      감사합니다.^_____^!!!
                    • enqn192
                      궁금한게 있어서 질문올립니다.
                      함수 안에 for문이 있으면 재귀함수로 다시 콜이 될 때도 for문이 동작하지 않는가 해서요.
                      for문이 동작하지 않아야지 저런 결과가 나올것 같은데 아니네요
                      지금 생각으로는 for문이 함수 내에 있어서 재귀함수가 콜될때 마다 for문이 새롭게 동작하여
                      위의 a태그만 골라내는 조건문이 없을 경우엔 body, ul, li, a, ..., ul 까지 모두 출력된 후에 맨 처음 태그인 body를 뺀 모든 태그가 출력되고 그렇게 마지막엔 ul태그만 출력될 것 같은 생각이 들거든요
                      즉, 처음에 c가 body.childNodes 인 상태로 for문이 동작하여 body.childNodes[1] = ul이 되고 이 ul 태그 가 또다시 c = ul.childNodes인 상태로 for문 안에서 ul.childNodes[1] = li 이 되고... 이렇게 되어 결국 중복되는 출력이 많을것 같은데 아니네요.

                      궁금합니다..
                    • crable
                      감사합니다.
                    • Byeong Heon Lee
                      너무 감사합니다~
                    • 신입1
                      항상 감사합니다.
                    • 유유
                      감사합니다!
                    • hyuna
                      감사합니다
                    • tachyon
                      감사합니다
                    • yihsang
                      재귀함수와 콜백...
                      잘 보았습니다. 감사합니다.
                    • JustStudy
                      2016.07.08 금
                      고맙습니다 3.
                    • JustStudy
                      2016.07.30금
                      고맙습니다 2.
                    • 이주환
                      2016. 04. 27
                      잘보고 갑니다~!
                    • JustStudy
                      고맙습니다
                    버전 관리
                    egoing
                    현재 버전
                    선택 버전
                    graphittie 자세히 보기