[javascript] JavaScript의 querySelector 및 querySelectorAll vs getElementsByClassName 및 getElementById

나는 정확히의 차이점이 무엇인지 알고 싶습니다 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")은 효과가 있습니다. 어떤 아이디어가 있습니까?



답변

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

구문 및 브라우저 지원

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

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

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

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

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


답변

Mozilla 문서 에서 수집 :

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

querySelector

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

querySelectorAll

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

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


답변

차이점에 대해, 사이의 결과에 중요한 하나가 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>


답변

이 답변, 난을 참조 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 *는 배치와 상관없이 대략 같은 시간 내에 요소를 찾습니다.


답변

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

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


답변

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

'#id.class:pseudo'

// or

'tag #id .class .class.class'

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

'class'

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

'id'


답변

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

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