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