JavaScript의 querySelector 및 querySelectorAll vs getElementsByClassName 및 getElementById


165

나는 정확히의 차이점이 무엇인지 알고 싶습니다 querySelectorquerySelectorAll대한 getElementsByClassName그리고 getElementById?

에서 이 링크 내가 가진 것을 수집 할 수 querySelector내가 쓸 수있는 document.querySelector(".myclass")클래스 요소를 얻을 myclass하고 document.querySelector("#myid")ID와 요소를 얻을 myid. 하지만 난 이미 할 수있는 getElementsByClassName과를 getElementById. 어느 것이 선호되어야합니까?

또한 ID가 콜론으로 동적으로 생성되고 다음과 같이 보이는 XPage 에서 작업 합니다 view:_id1:inputText1. 그래서 쓸 때 document.querySelector("#view:_id1:inputText1")작동하지 않습니다. 그러나 작문 document.getElementById("view:_id1:inputText1")은 효과가 있습니다. 어떤 아이디어가 있습니까?


1
querySelector는 HTML DOM 트리를 쿼리하는 데 사용되며 HTML 요소와 그 속성을 쿼리의 핵심 요소로 포함 할 수 있습니다. 정규 표현식을 사용하여이를 달성 할 수 있습니다. dojo.query ()도 같은 작업을 수행합니다
anix

1
당신은 의미하지 document.querySelectorAll(".myclass")않습니까? 를 사용 document.querySelector(".myclass")하면 일치하는 첫 번째 요소 만 반환됩니다.
mhatch

답변:


113

getElementsByClassName과 getElementById에 대해 querySelector와 querySelectorAll의 차이점이 정확히 무엇인지 알고 싶습니다.

구문 및 브라우저 지원

querySelector 더 복잡한 선택기를 사용하려는 경우 더 유용합니다.

예를 들어 foo 클래스의 멤버 인 요소의 모든 목록 항목 .foo li

document.querySelector ( "# view : _id1 : inputText1") 작동하지 않습니다. 그러나 document.getElementById ( "view : _id1 : inputText1") 작성이 작동합니다. 어떤 아이디어가 있습니까?

:문자 선택기 내부에 특별한 의미가 있습니다. 당신은 그것을 탈출해야합니다. 선택기 이스케이프 문자는 JS 문자열에서도 특별한 의미를 가지므로 이스케이프 문자도 이스케이프 해야 합니다.

document.querySelector("#view\\:_id1\\:inputText1")

3
브라우저마다 (버전마다) 다를 수 있습니다. 선택기 기반의 선택기가 더 비싸다고 생각하지만 (중요하지는 않을 것입니다)
Quentin

1
@janaspage의 진술을지지합니다. 오늘 사이트도 다운되었습니다.
doplumi

6
클래스 선택에 대해서는 jsperf.com/getelementsbyclassname-vs-queryselectorall/25 도 참조하십시오 . 결론 : 사람이 훨씬 더 순수 JQuery와보다 자바 스크립트 및 특정 기능을 선호한다 getElementByIdgetElementsByClassName. className 선택은 없이 수백 배 느려질 수 있습니다 getElementsByClassName.
Atrahasis

101

Mozilla 문서 에서 수집 :

NodeSelector 인터페이스이 사양은 Document, DocumentFragment 또는 Element 인터페이스를 구현하는 모든 객체에 두 가지 새로운 메소드를 추가합니다.

querySelector

노드의 서브 트리 내 에서 첫 번째로 일치하는 Element 노드를 리턴합니다 . 일치하는 노드가 없으면 null이 반환됩니다.

querySelectorAll

노드의 서브 트리 내에서 일치하는 모든 Element 노드를 포함 하는 NodeList를 리턴 하거나 일치하는 것이 없으면 빈 NodeList를 리턴합니다 .

참고 :에 의해 반환 된 NodeList querySelectorAll()는 활성 상태가 아니므로 DOM의 변경 사항이 컬렉션에 반영되지 않습니다. 이것은 라이브 노드 목록을 반환하는 다른 DOM 쿼리 방법과 다릅니다.


32
라이브 노드 목록 구별을 표시하기위한 +1 결과를 사용하려는 방식에 따라 알아야 할 매우 중요한 차이점입니다.
jmbpiano

7
"live"는 DOM 런타임에 추가 된 노드를 의미하며 newley 추가 노드에서 작동 할 수 있습니다.
diEcho

83

차이점에 대해, 사이의 결과에 중요한 하나가 querySelectorAllgetElementsByClassName: 반환 값이 다릅니다. querySelectorAll정적 컬렉션을 getElementsByClassName반환하고 라이브 컬렉션 을 반환합니다. 나중에 사용할 수 있도록 결과를 변수에 저장하면 혼동 될 수 있습니다.

  • 로 생성 된 변수 에는 메소드가 호출 된 시점에서querySelectorAll 선택기를 수행 한 요소가 포함됩니다 .
  • 로 생성 된 변수 getElementsByClassName에는 선택기를 사용할 때 선택기를 이행 한 요소가 포함 됩니다 (메소드가 호출 된 순간과 다를 수 있음).

예를 들어 변수를 다시 할당하지 않아도 클래스를 업데이트 한 후 변수 aux1aux2값 이 어떻게 다른지 확인하십시오 .

// storing all the elements with class "blue" using the two methods
var aux1 = document.querySelectorAll(".blue");
var aux2 = document.getElementsByClassName("blue");

// write the number of elements in each array (values match)
console.log("Number of elements with querySelectorAll = " + aux1.length);
console.log("Number of elements with getElementsByClassName = " + aux2.length);

// change one element's class to "blue"
document.getElementById("div1").className = "blue";

// write the number of elements in each array (values differ)
console.log("Number of elements with querySelectorAll = " + aux1.length);
console.log("Number of elements with getElementsByClassName = " + aux2.length);
.red { color:red; }
.green { color:green; }
.blue { color:blue; }
<div id="div0" class="blue">Blue</div>
<div id="div1" class="red">Red</div>
<div id="div2" class="green">Green</div>


2
그냥 언급 - 모든 기존의 DOM API를 즉 노드 목록을 반환 document.getElementsByName, document.getElementsByTagNameNS또는 document.getElementsByTagName동일한 동작을 전시 할 예정이다.
RBT

2
일부 분석에 따르면 querySelector는 getElementById보다 시간이 오래 걸립니다 . dimlucas.com/index.php/2016/09/17/… 액세스 시간을 고려하면 어떻게됩니까? getElementById에서 얻은 라이브 노드가 querySelector의 정적 노드보다 시간이 더 걸립니까?
Eric

1
@RBT이 오래된 DOM API는 NodeList 객체를 반환하지 않고 HTMLCollection을 반환한다고 언급했습니다.
Miscreant

@Eric document.getElementById()은 라이브 노드를 반환하지 않습니다. CSS 선택기를 먼저 구문 분석해야하기 document.querySelector('#id_here')때문에 아마도 더 빠릅니다 querySelector.
Miscreant

68

이 답변, 난을 참조 querySelector하고 querySelectorAll*과에 querySelector로 getElementById, getElementsByClassName, getElementsByTagName, 및 getElementsByNamegetElement로 *.

주요 차이점

  1. querySelector *는 id, tag 또는 class에 대한 단순한 선택기뿐만 아니라 모든 CSS3 선택기에 전달할 수 있으므로 더 유연합니다.
  2. querySelector의 성능 은 호출 된 DOM의 크기에 따라 변경됩니다. * 정확하게 말하면, querySelector * 호출은 O (n) 시간에 실행되고 getElement * 호출은 O (1) 시간에 실행됩니다. 여기서 n은 호출 된 요소 또는 문서의 모든 하위의 총 수입니다. 이 사실은 가장 잘 알려지지 않은 것 같습니다. 대담합니다.
  3. getElement * 호출은 DOM에 대한 직접 참조를 리턴하는 반면 querySelector *는 내부적으로 선택된 요소를 참조하기 전에 선택된 요소의 사본을 작성합니다. 이를 "실시간"및 "정적"요소라고합니다. 이것은 그들이 반환하는 유형과 엄격하게 관련이 없습니다. 요소가 어느 시점에 복사되었는지 여부에 따라 다르며 데이터의 본질적인 속성이 아니기 때문에 프로그래밍 방식으로 요소가 라이브인지 정적인지 알 수있는 방법이 없습니다. 라이브 요소에 대한 변경 사항은 즉시 적용됩니다. 라이브 요소를 변경하면 DOM에서 직접 변경되므로 JS의 다음 줄에서 해당 변경 사항을 볼 수 있으며 해당 요소를 즉시 참조하는 다른 라이브 요소로 전파됩니다. 정적 요소에 대한 변경 사항은 현재 스크립트 실행이 완료된 후에 만 ​​DOM에 다시 쓰여집니다.
  4. 이러한 통화의 반환 유형은 다양합니다. querySelector그리고 getElementById모두 하나의 요소를 반환합니다. querySelectorAll그리고 getElementsByName둘 다 HTMLCollection이 유행을 벗어난 후에 추가 된 새로운 함수 인 NodeList를 반환합니다. 이전 getElementsByClassNamegetElementsByTagName둘 다 HTMLCollection을 반환합니다. 다시 말하지만 이것은 본질적으로 요소가 살아 있는지 또는 정적인지와 관련이 없습니다.

이러한 개념은 다음 표에 요약되어 있습니다.

Function               | Live? | Type           | Time Complexity
querySelector          |   N   | Element        |  O(n)
querySelectorAll       |   N   | NodeList       |  O(n)
getElementById         |   Y   | Element        |  O(1)
getElementsByClassName |   Y   | HTMLCollection |  O(1)
getElementsByTagName   |   Y   | HTMLCollection |  O(1)
getElementsByName      |   Y   | NodeList       |  O(1)

세부 사항, 팁 및 예

  • HTMLCollection은 NodeLists만큼 배열과 유사하지 않으며 .forEach ()를 지원하지 않습니다. 스프레드 연산자 가이 문제를 해결하는 데 유용하다는 것을 알았습니다.

    [...document.getElementsByClassName("someClass")].forEach()

  • 모든 요소, 글로벌는 document, 이러한 제외한 모든 기능에 액세스 할 수 있습니다 getElementByIdgetElementsByName에서만 구현됩니다, document.

  • querySelector *를 사용하는 대신 getElement * 호출을 연결하면 특히 대규모 DOM에서 성능이 향상됩니다. 작은 DOM 및 / 또는 매우 긴 체인에서도 일반적으로 더 빠릅니다. 그러나 성능이 필요하다는 것을 알지 못하면 querySelector *의 가독성이 선호되어야합니다. querySelectorAll모든 단계에서 NodeList 또는 HTMLCollection에서 요소를 선택해야하기 때문에 종종 다시 쓰기가 더 어렵습니다. 예를 들어 다음 코드는 작동 하지 않습니다 .

document.getElementsByClassName("someClass").getElementsByTagName("div")

because you can only use getElements* on single elements, not collections. For example:

`document.querySelector("#someId .someClass div")`

could be written as:

document.getElementById("someId").getElementsByClassName("someClass")[0].getElementsByTagName("div")[0]

Note the use of `[0]` to get just the first element of the collection at each step that returns a collection, resulting in one element at the end just like with `querySelector`.
  • 모든 요소가 querySelector * 및 getElement * 호출에 모두 액세스 할 수 있으므로 두 호출을 모두 사용하여 체인을 작성할 수 있습니다. 이는 성능 향상을 원할 경우 유용하지만 getElement * 호출의 관점에서 작성할 수없는 querySelector를 피할 수는 없습니다. .

  • getElement * 호출 만 사용하여 선택기를 작성할 수 있는지는 일반적으로 쉽게 알 수 있지만 명확하지 않은 경우가 있습니다.

    document.querySelectorAll(".class1.class2")

    로 다시 쓸 수 있습니다

    document.getElementsByClassName("class1 class2")

  • querySelector *로 가져온 정적 요소에서 getElement *를 사용하면 querySelector에 의해 복사 된 DOM의 정적 서브 세트와 관련하여 존재하지만 전체 문서 DOM과 관련하여 존재하지 않는 요소가 생성됩니다. 요소의 실시간 / 정적 해석이 분리되기 시작합니다. 이에 대해 걱정해야하는 상황은 피해야하지만, 그렇게하는 경우 querySelector *는 참조를 리턴하기 전에 찾은 copy 요소를 호출하지만 getElement * 호출은 복사하지 않고 직접 참조를 가져옵니다.

  • 일치하는 항목이 여러 개인 경우 API 중 어느 것을 먼저 선택해야하는지 지정하지 않습니다.

  • querySelector *는 일치하는 것을 찾을 때까지 DOM을 반복하므로 (주요 차이점 # 2 참조) 위의 내용은 DOM에서 찾고있는 요소의 위치에 의존하여 신속하게 찾을 수 있음을 의미합니다. 브라우저는 DOM을 거꾸로, 앞으로, 깊이 우선, 너비 우선 또는 기타 방식으로 반복 할 수 있습니다. getElement *는 배치와 상관없이 대략 같은 시간 내에 요소를 찾습니다.


4
지금까지이 주제에 대한 가장 정확한 답변입니다. 더 많이 공언해야합니다.
SeaWarrior404

블로그, 사샤에 넣어해야합니다 매우 정확한
theking2

25

성능 측면에서 사용하는 더 좋은 방법을 찾기 위해 순전히이 페이지에 왔습니다.

querySelector / querySelectorAll or getElementsByClassName

나는 이것을 발견했다 : https://jsperf.com/getelementsbyclassname-vs-queryselectorall/18

위의 2 x 예제에서 테스트를 수행하고 jQuery의 동등한 선택기 테스트에서도 척킹합니다. 내 테스트 결과는 다음과 같습니다.

getElementsByClassName = 1,138,018 operations / sec - <<< clear winner
querySelectorAll = 39,033 operations / sec
jquery select = 381,648 operations / sec

1
와우, 그것은 차이입니다, 그것을 찾아 주셔서 감사합니다. 분명히 querySelectorAll하면서, (선택기 식을 구문 분석 의사 요소 등 회계 포함) 장면 뒤에 추가 작업을 필요로 getElementsByClassName단지 재귀 객체 탐색이다.
John Weisz

18

querySelector 다음과 같이 ID와 클래스 및 의사 클래스가 포함 된 완전한 CSS (3) 선택 자일 수 있습니다.

'#id.class:pseudo'

// or

'tag #id .class .class.class'

으로 getElementByClassName당신은 단지 클래스를 정의 할 수 있습니다

'class'

으로 getElementById당신은 단지 ID를 정의 할 수 있습니다

'id'

1
:firstCSS의 선택은 지금? :first-class또는 :first-of-type어쩌면 :firstJavaScript / jQuery / Sizzle 추가 라고 생각했습니다 .
데이비드는 모니카 복원

@DavidThomas 네, CSS3의 일부입니다. 다음과 같이 사용할 수 있습니다 : css-tricks.com/almanac/selectors/f/first-child
알고리즘 리듬

2
그러나 :first눈에 띄게 아닙니다 :first-child.
데이비드는 모니카가

3
"선택자에 의사 요소를 사용할 수는 있지만 문서의 요소와 일치하지 않으므로 요소가 반환되지 않습니다. 따라서 의사는 의사의 사용을 피해야합니다. 이 사양에 정의 된 방법으로 전달되는 선택기의 요소 " w3.org/TR/selectors-api/#grammar
리치 레머

또한 IE에는 의사 요소를 선택할 때 빈 요소 목록 대신 루트 html 요소를 반환하는 버그가 있습니다 (물론).
풍부한 remer

7

querySelector그리고 querySelectorAll비교적 새로운 API를, 반면 getElementByIdgetElementsByClassName 많은 이상 우리와 함께 있었다. 즉, 사용하는 것은 대부분 지원해야하는 브라우저에 따라 다릅니다.

에 대해서는 :특별한 의미가 있으므로 ID / 클래스 이름의 일부로 사용해야하는 경우에는 이스케이프해야합니다.


13
반드시 그런 것은 아닙니다. 예를 들어 querySelectorAllIE8에서는 사용할 수 있지만 getElementsByClassName그렇지 않습니다.
DaveJ

querySelectorAll... 기본적으로 모든 것 : caniuse.com/#search=querySelectorAll
dsdsdsdsd

1
@Naveen getelementsbyclassname vs querySelectorAll vs jquery select 가 도움이 될 수 있습니다.
lowtechsun

5

querySelectorw3c 선택기 API입니다

getElementByw3c DOM API입니다

IMO의 가장 큰 차이점은의 반환 유형이 querySelectorAll정적 노드 목록이고 getElementsBy라이브 노드 목록이라는 점입니다. 따라서 데모 2의 루핑 lis은 활성 상태 이므로 각 반복 중에 자체 업데이트 되므로 종료되지 않습니다 .

// Demo 1 correct
var ul = document.querySelectorAll('ul')[0],
    lis = ul.querySelectorAll("li");
for(var i = 0; i < lis.length ; i++){
    ul.appendChild(document.createElement("li"));
}

// Demo 2 wrong
var ul = document.getElementsByTagName('ul')[0], 
    lis = ul.getElementsByTagName("li"); 
for(var i = 0; i < lis.length ; i++){
    ul.appendChild(document.createElement("li")); 
}

4

"querySelector"와 "querySelectorAll"의 차이점

//querySelector returns single element
let listsingle = document.querySelector('li');
console.log(listsingle);


//querySelectorAll returns lit/array of elements
let list = document.querySelectorAll('li');
console.log(list);


//Note : output will be visible in Console
<ul>
<li class="test">ffff</li>
<li class="test">vvvv</li>
<li>dddd</li>
<li class="test">ddff</li>
</ul>


2

이거 봐요

https://codepen.io/bagdaulet/pen/bzdKjL

25 %에서 querySelector보다 빠른 getElementById

jquery가 가장 느립니다

var q = time_my_script(function() {

    for (i = 0; i < 1000000; i++) {
         var w = document.querySelector('#ll');
    }

});

console.log('querySelector: '+q+'ms');

-3

querySelector와 getlementbyID (Claassname, Tagname 등)의 주요 차이점은 querySelector는 하나의 출력 만 리턴하는 반면 getElementBy *는 모든 요소를 ​​리턴하는 조건을 만족시키는 요소가 둘 이상있는 경우입니다.

더 명확하게하기 위해 예를 고려해 봅시다.

 <nav id="primary" class="menu">
                            <a class="link" href="#">For Business</a>
                            <a class="link" href="#">Become an Instructor</a>
                            <a class="link" href="#">Mobile Applications</a>
                            <a class="link" href="#">Support</a>
                            <a class="link" href="#">Help</a>
   </nav> 

아래 코드는 차이점을 설명합니다

**QUERY SELECTOR**
document.querySelector('.link'); // Output : For Business (element)

document.querySelectorAll('.link'); //Out All the element with class link

**GET ELEMENT**
document.getElementsByClassName('link') // Output : will return all the element with a class "link" but whereas in query selector it will return only one element which encounters first.

queryslector를 위해 단일 요소를 선택하거나 getElement를 위해 여러 요소를 선택하려는 경우 간단히


1
getElementById는 하나의 요소 만 반환하지만이 둘의 차이점은 아닙니다.
Timofey 'Sasha'Kondrashov
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.