Javascript : 페이지의 모든 DOM 요소를 반복하는 방법은 무엇입니까?


162

페이지의 모든 요소를 ​​반복하려고하므로이 페이지에 존재하는 모든 요소에서 특수 클래스를 확인하고 싶습니다.

그렇다면 모든 요소를 ​​확인하고 싶다고 어떻게 말합니까?


1
모든 요소를 ​​직접 반복 하시겠습니까? 특정 클래스의 요소를 가져 오기 위해 jquery 및 선택기를 사용하지 않는 이유는 무엇입니까?
NG.

document.getElementsByTagName 메서드가 없습니까?
SuperJedi224

* TL; DR : 표시 전용 요소의 경우 다음을 사용합니다.document.body.getElementsByTagName('*')
Andrew

반복 :for (... of ...) { }
Andrew

사용 :Array.from(document.querySelectorAll('*')).forEach(el => {})
yaya

답변:


266

당신은 전달할 수 있습니다 *getElementsByTagName()이 페이지에있는 모든 요소를 반환되도록 :

var all = document.getElementsByTagName("*");

for (var i=0, max=all.length; i < max; i++) {
     // Do something with the element here
}

사용 querySelectorAll()가능한 경우 (IE9 +, IE8의 CSS)을 사용하여 특정 클래스가있는 요소를 찾을 수 있습니다.

if (document.querySelectorAll)
    var clsElements = document.querySelectorAll(".mySpeshalClass");
else
    // loop through all elements instead

이것은 확실히 최신 브라우저의 문제를 가속화 할 것입니다.


브라우저는 이제 NodeList에서 foreach를 지원 합니다. 즉, 자신 만의 for 루프를 작성하는 대신 요소를 직접 루프 할 수 있습니다.

document.querySelectorAll('*').forEach(function(node) {
    // Do whatever you want with the node object.
});

성능 참고 사항 -특정 선택기를 사용하여 찾고있는 범위를 정하기 위해 최선을 다하십시오. 범용 선택기는 페이지의 복잡성에 따라 많은 노드를 반환 할 수 있습니다. 또한 아이들을 신경 쓰지 않을 때 document.body.querySelectorAll대신 사용 하는 것을 고려하십시오 .document.querySelectorAll<head>


2
이 방법은 매우 멋져 보이지만 위 방법에서 요소를 어떻게 선택할 수 있습니까? 색인 'i'만 얻었습니까?
Florian Müller

2
@Florian : 배열 요소에 액세스하는 것처럼- all[i]현재 요소를 제공합니다.
Andy E

2
루프 측면에서 요소를 선택하는 방법은 무엇입니까?
Debiprasad

2
@JesseAldridge : 습관 / 좋은 연습의 힘입니다. 모든 반복에서 속성 조회를 피하는 것은 일반적으로 마이크로 최적화이지만 작성하기가 특히 어렵지 않으므로 자연스럽게 수행합니다.
Andy E

2
@Jonathan getElementsByClassName()querySelectorAll()(전자는 IE 8에서 지원되지 않음) 보다 더 나쁜 지원을 제공 합니다. OP 는 페이지의 모든 요소 를 반복하고 싶다고 분명히 밝혔으며 , 이에 대한 해결책을 제시하고 대안을 제시했습니다. 나는 그 문제가 무엇인지 잘 모르겠습니다 ;-).
Andy E

40

같은 것을 찾고 있었다. 음, 정확히는 아닙니다. 모든 DOM 노드를 나열하고 싶었습니다.

var currentNode,
    ni = document.createNodeIterator(document.documentElement, NodeFilter.SHOW_ELEMENT);

while(currentNode = ni.nextNode()) {
    console.log(currentNode.nodeName);
}

특정 클래스의 요소를 얻으려면 필터 기능을 사용할 수 있습니다.

var currentNode,
    ni = document.createNodeIterator(
                     document.documentElement, 
                     NodeFilter.SHOW_ELEMENT,
                     function(node){
                         return node.classList.contains('toggleable') ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
                     }
         );

while(currentNode = ni.nextNode()) {
    console.log(currentNode.nodeName);
}

MDN 에서 솔루션을 찾았습니다.


document.ceeateNodeIterator를 본 적이 없습니다. JS이 가져 오는 어떤 새로운 기능 흥미로운 것 같습니다)
플로리안 뮐러

2
이것의 멋진 기능은 nodeiterator가 html에 나타나는 순서대로 노드를 걷는다는 것입니다. 일부가 document.body.getElementsByTagName('*')스크램블 된 순서로 노드를 반환 할 수 있는지 궁금합니다 .
민간인

와우, 실제로 잘 지원됩니다!
rogerdpack

16

항상 가장 좋은 해결책은 재귀를 사용하는 것입니다.

loop(document);
function loop(node){
    // do some thing with the node here
    var nodes = node.childNodes;
    for (var i = 0; i <nodes.length; i++){
        if(!nodes[i]){
            continue;
        }

        if(nodes[i].childNodes.length > 0){
            loop(nodes[i]);
        }
    }
}

다른 제안과 달리이 솔루션은 모든 노드에 대해 배열을 만들 필요가 없으므로 메모리에 더 많은 빛이 들어옵니다. 더 중요한 것은 더 많은 결과를 찾는다는 것입니다. 그 결과가 무엇인지 잘 모르겠지만 크롬에서 테스트 할 때에 비해 약 50 % 더 많은 노드가 발견됩니다.document.getElementsByTagName("*");


20
재귀를 사용하기에 가장 좋은 시간은 재귀를 사용하기에 가장 좋은 시간입니다.
Adamlive

9
"에 비해 약 50 % 더 많은 노드를 document.getElementsByTagName("*");찾았습니다."— 네, 텍스트 노드와 주석 노드는 물론 요소 노드도 찾을 수 있습니다. OP가 요소에 대해 묻는 것이기 때문에 불필요합니다.
Paul D. Waite

2
그것은 수있는 메모리 가볍다. 각 재귀 수준에서 얼마나 많은 일을하는지에 따라 바닥에 도달 할 때까지 엄청나게 큰 호출 스택을 구축 할 수 있습니다. A NodeList는 단순히 NodeDOM에 이미 빌드 된를 참조하는 것이므로 상상하는 것만 큼 무겁지 않습니다. 더 많이 아는 사람은 무게를 잴 수 있지만 메모리 참조 크기 일 뿐이므로 노드 당 8 바이트입니다.
Qaribou에서 Josh

9

다음은 문서 또는 요소를 반복하는 방법에 대한 또 다른 예입니다.

function getNodeList(elem){
var l=new Array(elem),c=1,ret=new Array();
//This first loop will loop until the count var is stable//
for(var r=0;r<c;r++){
    //This loop will loop thru the child element list//
    for(var z=0;z<l[r].childNodes.length;z++){

         //Push the element to the return array.
        ret.push(l[r].childNodes[z]);

        if(l[r].childNodes[z].childNodes[0]){
            l.push(l[r].childNodes[z]);c++;
        }//IF           
    }//FOR
}//FOR
return ret;
}


3

Andy E.가 좋은 대답을했습니다.

특정 선택기에서 모든 자식을 선택하려는 경우 (최근에이 작업이 필요함) 원하는 DOM 개체에 "getElementsByTagName ()"메서드를 적용 할 수 있습니다.

예를 들어, 웹 페이지의 "시각적"부분을 구문 분석해야했기 때문에

var visualDomElts = document.body.getElementsByTagName('*');

이것은 머리 부분을 고려하지 않습니다.


2

이 링크에서
자바 스크립트 참조

<html>
<head>
<title>A Simple Page</title>
<script language="JavaScript">
<!--
function findhead1()
{
    var tag, tags;
    // or you can use var allElem=document.all; and loop on it
    tags = "The tags in the page are:"
    for(i = 0; i < document.all.length; i++)
    {
        tag = document.all(i).tagName;
        tags = tags + "\r" + tag;
    }
    document.write(tags);
}

//  -->
</script>
</head>
<body onload="findhead1()">
<h1>Heading One</h1>
</body>
</html>

업데이트 : 편집

내 마지막 답변 이후로 더 나은 간단한 해결책을 찾았습니다.

function search(tableEvent)
    {
        clearResults()

        document.getElementById('loading').style.display = 'block';

        var params = 'formAction=SearchStocks';

        var elemArray = document.mainForm.elements;
        for (var i = 0; i < elemArray.length;i++)
        {
            var element = elemArray[i];

            var elementName= element.name;
            if(elementName=='formAction')
                continue;
            params += '&' + elementName+'='+ encodeURIComponent(element.value);

        }

        params += '&tableEvent=' + tableEvent;


        createXmlHttpObject();

        sendRequestPost(http_request,'Controller',false,params);

        prepareUpdateTableContents();//function js to handle the response out of scope for this question

    }

이 SO 토론 에 따르면 , document.all찬성은 권장되지 않습니다 document.getElementBy*.
thejoshwolfe

@thejoshwolfe 당신은 내가 업데이트 내 socond 솔루션에 대해 어떻게 생각하십니까 덕분에
샤리프

0

사용하다 *

var allElem = document.getElementsByTagName("*");
for (var i = 0; i < allElem.length; i++) {
    // Do something with all element here
}

0

정말 빠르다고 생각합니다

document.querySelectorAll('body,body *').forEach(function(e) {

0

모든 요소 var all = document.getElementsByTagName("*"); for (var i=0, max=all.length; i < max; i++);를 확인해야하는 경우 모든 요소를 ​​사용하는 것은 괜찮지 만 반복되는 요소 나 텍스트를 확인하거나 반복하게됩니다.

다음은 모든 DOM 요소의 각 요소를 한 번만 확인하거나 반복 하고 추가 하는 재귀 구현입니다 .

(@George Reith의 재귀 답변에 대한 크레딧 : Map HTML to JSON )

function mapDOMCheck(html_string, json) {
  treeObject = {}

  dom = new jsdom.JSDOM(html_string) // use jsdom because DOMParser does not provide client-side Window for element access
  document = dom.window.document
  element = document.querySelector('html')

  // Recurse and loop through DOM elements only once
  function treeHTML(element, object) {
    var nodeList = element.childNodes;

    if (nodeList != null) {
      if (nodeList.length) {
        object[element.nodeName] = []; // IMPT: empty [] array for parent node to push non-text recursivable elements (see below)

        for (var i = 0; i < nodeList.length; i++) {
          console.log("nodeName", nodeList[i].nodeName);

          if (nodeList[i].nodeType == 3) { // if child node is **final base-case** text node
            console.log("nodeValue", nodeList[i].nodeValue);
          } else { // else
            object[element.nodeName].push({}); // push {} into empty [] array where {} for recursivable elements
            treeHTML(nodeList[i], object[element.nodeName][object[element.nodeName].length - 1]);
          }
        }
      }
    }
  }

  treeHTML(element, treeObject);

}

-1

시도해 볼 수 있습니다. document.getElementsByClassName('special_class');


4
올바른 방법은 getElementsByClassName()Internet Explorer에서 버전 9까지 지원되지 않는 것입니다.
Andy E
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.