JavaScript 中的 querySelector 和 querySelectorAll 与 getElementsByClassName 和 getElementById
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14377590/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
querySelector and querySelectorAll vs getElementsByClassName and getElementById in JavaScript
提问by Naveen
I would like to know what exactly is the difference between querySelectorand querySelectorAllagainst getElementsByClassNameand getElementById?
我想知道querySelector和querySelectorAll反对 getElementsByClassName和到底有什么区别getElementById?
From this linkI could gather that with querySelectorI can write document.querySelector(".myclass")to get elements with class myclassand document.querySelector("#myid")to get element with ID myid. But I can already do that getElementsByClassNameand getElementById. Which one should be preferred?
从这个链接我可以收集到,querySelector我可以写document.querySelector(".myclass")来获取带有类的元素myclass并document.querySelector("#myid")获取带有 ID 的元素myid。但我已经可以做到这一点getElementsByClassName和getElementById。应该首选哪一个?
Also I work in XPageswhere the ID is dynamically generated with colon and looks like this view:_id1:inputText1. So when I write document.querySelector("#view:_id1:inputText1")it doesn't work. But writing document.getElementById("view:_id1:inputText1")works. Any ideas why?
我还在XPage中工作,其中 ID 是用冒号动态生成的,看起来像这样view:_id1:inputText1。所以当我写document.querySelector("#view:_id1:inputText1")它不起作用。但写作document.getElementById("view:_id1:inputText1")有效。任何想法为什么?
采纳答案by Quentin
I would like to know what exactly is the difference between querySelector and querySelectorAll against getElementsByClassName and getElementById?
我想知道 querySelector 和 querySelectorAll 与 getElementsByClassName 和 getElementById 的区别究竟是什么?
The syntax and the browser support.
语法和浏览器支持。
querySelectoris more useful when you want to use more complex selectors.
querySelector当您想使用更复杂的选择器时更有用。
e.g. All list items descended from an element that is a member of the foo class: .foo li
例如,从属于 foo 类成员的元素派生的所有列表项: .foo li
document.querySelector("#view:_id1:inputText1") it doesn't work. But writing document.getElementById("view:_id1:inputText1") works. Any ideas why?
document.querySelector("#view:_id1:inputText1") 它不起作用。但是写 document.getElementById("view:_id1:inputText1") 有效。任何想法为什么?
The :character has special meaning inside a selector. You have to escape it. (The selector escape character has special meaning in a JS string too, so you have to escape thattoo).
该:字符在选择器中具有特殊含义。你必须逃避它。(选择器转义字符在一个字符串JS特殊的意义,所以你必须逃离这太)。
document.querySelector("#view\:_id1\:inputText1")
回答by diEcho
collecting from Mozilla Documentation:
从Mozilla 文档中收集:
The NodeSelector interface This specification adds two new methods to any objects implementing the Document, DocumentFragment, or Element interfaces:
NodeSelector 接口 此规范向实现 Document、DocumentFragment 或 Element 接口的任何对象添加了两个新方法:
querySelector
查询选择器
Returns the first matching Element nodewithin the node's subtree. If no matching node is found, null is returned.
返回节点子树中第一个匹配的 Element 节点。如果没有找到匹配的节点,则返回 null。
querySelectorAll
查询选择器全部
Returns a NodeList containing all matching Elementnodes within the node's subtree, or an empty NodeList if no matches are found.
返回一个包含节点子树中所有匹配元素节点的 NodeList,如果没有找到匹配,则返回一个空的 NodeList。
and
和
Note: The NodeList returned by
querySelectorAll()is not live, which means that changes in the DOM are not reflected in the collection. This is different from other DOM querying methods that return live node lists.
注意: 返回的 NodeList
querySelectorAll()不是 live 的,这意味着 DOM 的变化不会反映在集合中。这与返回活动节点列表的其他 DOM 查询方法不同。
回答by Alvaro Montoro
About the differences, there is an important one in the results between querySelectorAlland getElementsByClassName: the return value is different. querySelectorAllwill return a static collection, while getElementsByClassNamereturns a live collection. This could lead to confusion if you store the results in a variable for later use:
关于区别,querySelectorAll和之间的结果有一个重要的地方getElementsByClassName:返回值不同。querySelectorAll将返回一个静态集合,而getElementsByClassName返回一个实时集合。如果将结果存储在变量中供以后使用,这可能会导致混淆:
- A variable generated with
querySelectorAllwill contain the elements that fulfilled the selector at the moment the method was called. - A variable generated with
getElementsByClassNamewill contain the elements that fulfilled the selector when it is used(that may be different from the moment the method was called).
- 生成的变量
querySelectorAll将包含在调用方法时满足选择器的元素。 - 生成的变量
getElementsByClassName将包含使用时满足选择器的元素(这可能与调用方法的时刻不同)。
For example, notice how even if you haven't reassigned the variables aux1and aux2, they contain different values after updating the classes:
例如,请注意即使您没有重新分配变量aux1和aux2,它们在更新类后也会包含不同的值:
// 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>
回答by Timofey 'Sasha' Kondrashov
For this answer, I refer to querySelectorand querySelectorAllas querySelector* and to getElementById, getElementsByClassName, getElementsByTagName, and getElementsByNameas getElement*.
对于这样的回答,我指的是querySelector和querySelectorAll作为querySelector *和getElementById,getElementsByClassName,getElementsByTagName,和getElementsByName作为getElement *。
Main Differences
主要区别
- querySelector* is more flexible, as you can pass it any CSS3 selector, not just simple ones for id, tag, or class.
- The performance of querySelector* changes with the size of the DOM that it is invoked on.To be precise, querySelector* calls run in O(n) time and getElement* calls run in O(1) time, where n is the total number of all children of the element or document it is invoked on. This fact seems to be the least well-known, so I am bolding it.
- getElement* calls return direct references to the DOM, whereas querySelector* internally makes copies of the selected elements before returning references to them. These are referred to as "live" and "static" elements. This is NOT strictly related to the types that they return. There is no way I know of to tell if an element is live or static programmatically, as it depends on whether the element was copied at some point, and is not an intrinsic property of the data. Changes to live elements apply immediately - changing a live element changes it directly in the DOM, and therefore the very next line of JS can see that change, and it propagates to any other live elements referencing that element immediately. Changes to static elements are only written back to the DOM after the current script is done executing. These extra copy and write steps have some small, and generally negligible, effect on performance.
- The return types of these calls vary.
querySelectorandgetElementByIdboth return a single element.querySelectorAllandgetElementsByNameboth return NodeLists, being newer functions that were added after HTMLCollection went out of fashion. The oldergetElementsByClassNameandgetElementsByTagNameboth return HTMLCollections. Again, this is essentially irrelevant to whether the elements are live or static.
- querySelector* 更灵活,因为您可以将任何 CSS3 选择器传递给它,而不仅仅是 id、tag 或 class 的简单选择器。
- querySelector* 的性能随着调用它的 DOM 的大小而变化。准确地说,querySelector* 调用在 O(n) 时间内运行,getElement* 调用在 O(1) 时间内运行,其中 n 是调用它的元素或文档的所有子元素的总数。这个事实似乎是最不为人知的,所以我加粗了。
- getElement* 调用返回对 DOM 的直接引用,而 querySelector* 在返回对它们的引用之前在内部制作所选元素的副本。这些被称为“实时”和“静态”元素。这与它们返回的类型没有严格的关系。我不知道以编程方式判断元素是活动的还是静态的,因为这取决于元素是否在某个时候被复制,而不是数据的固有属性。对活动元素的更改立即应用 - 更改活动元素会直接在 DOM 中更改它,因此下一行 JS 可以看到该更改,并且它会立即传播到引用该元素的任何其他活动元素。对静态元素的更改仅在当前脚本执行完成后写回 DOM。
- 这些调用的返回类型各不相同。
querySelector并且getElementById都返回一个元素。querySelectorAll并且getElementsByName都返回 NodeLists,这是在 HTMLCollection 过时后添加的较新的函数。旧的getElementsByClassName和getElementsByTagName都返回 HTMLCollections。同样,这与元素是活动的还是静态的本质上无关。
These concepts are summarized in the following table.
下表总结了这些概念。
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)
Details, Tips, and Examples
详细信息、提示和示例
HTMLCollections are not as array-like as NodeLists and do not support .forEach(). I find the spread operator useful to work around this:
[...document.getElementsByClassName("someClass")].forEach()Every element, and the global
document, have access to all of these functions except forgetElementByIdandgetElementsByName, which are only implemented ondocument.Chaining getElement* calls instead of using querySelector* will improve performance, especially on very large DOMs. Even on small DOMs and/or with very long chains, it is generally faster. However, unless you know you need the performance, the readability of querySelector* should be preferred.
querySelectorAllis often harder to rewrite, because you must select elements from the NodeList or HTMLCollection at every step. For example, the following code does notwork: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 withquerySelector.Since all elements have access to both querySelector* and getElement* calls, you can make chains using both calls, which can be useful if you want some performance gain, but cannot avoid a querySelector that can not be written in terms of the getElement* calls.
Though it is generally easy to tell if a selector can be written using only getElement* calls, there is one case that may not be obvious:
document.querySelectorAll(".class1.class2")can be rewritten as
document.getElementsByClassName("class1 class2")Using getElement* on a static element fetched with querySelector* will result in an element that is live with respect to the static subset of the DOM copied by querySelector, but not live with respect to the full document DOM... this is where the simple live/static interpretation of elements begins to fall apart. You should probably avoid situations where you have to worry about this, but if you do, remember that querySelector* calls copy elements they find before returning references to them, but getElement* calls fetch direct references without copying.
Neither API specifies which element should be selected first if there are multiple matches.
Because
querySelectoriterates through the DOM until it finds a match (see Main Difference #2), the above also implies that you cannot rely on the position of an element you are looking for in the DOM to guarantee that it is found quickly - the browser may iterate through the DOM backwards, forwards, depth first, breadth first, or otherwise.
HTMLCollections 不像 NodeLists 那样类似于数组,并且不支持 .forEach()。我发现扩展运算符对解决此问题很有用:
[...document.getElementsByClassName("someClass")].forEach()document除了仅在 上实现的getElementByIdand之外,每个元素和 global都可以访问所有这些函数。getElementsByNamedocument链接 getElement* 调用而不是使用 querySelector* 将提高性能,尤其是在非常大的 DOM 上。即使在小型 DOM 和/或非常长的链上,它通常也更快。但是,除非您知道自己需要性能,否则应首选 querySelector* 的可读性。
querySelectorAll通常更难重写,因为您必须在每一步都从 NodeList 或 HTMLCollection 中选择元素。例如,下面的代码并不能正常工作:document.getElementsByClassName("someClass").getElementsByTagName("div")因为您只能在单个元素上使用 getElements*,而不能在集合上使用。例如:
document.querySelector("#someId .someClass div")可以写成:
document.getElementById("someId").getElementsByClassName("someClass")[0].getElementsByTagName("div")[0]请注意,
[0]在返回集合的每个步骤中,使用仅获取集合的第一个元素,就像 with 一样,在最后生成一个元素querySelector。由于所有元素都可以访问 querySelector* 和 getElement* 调用,因此您可以使用这两个调用创建链,如果您想要一些性能提升,这会很有用,但无法避免无法根据 getElement* 调用编写的 querySelector .
虽然通常很容易判断是否可以仅使用 getElement* 调用编写选择器,但有一种情况可能并不明显:
document.querySelectorAll(".class1.class2")可以改写为
document.getElementsByClassName("class1 class2")在使用 querySelector* 获取的静态元素上使用 getElement* 将导致元素相对于 querySelector 复制的 DOM 的静态子集有效,但相对于完整文档 DOM 无效......这是简单的地方对元素的实时/静态解释开始分崩离析。您可能应该避免不得不担心这一点的情况,但是如果您这样做了,请记住 querySelector* 在返回对它们的引用之前调用它们找到的复制元素,但 getElement* 调用获取直接引用而不进行复制。
如果有多个匹配项,两个 API 都没有指定应该首先选择哪个元素。
因为
querySelector遍历 DOM 直到找到匹配项(请参阅主要差异 #2),所以上面还暗示您不能依赖您在 DOM 中查找的元素的位置来保证它被快速找到 - 浏览器可能会向后、向前、深度优先、广度优先或其他方式遍历 DOM。
回答by OTurner
I came to this page purely to find out the better method to use in terms of performance - i.e. which is faster:
我来到此页面纯粹是为了找出在性能方面使用的更好方法 - 即更快:
querySelector / querySelectorAll or getElementsByClassName
and I found this: https://jsperf.com/getelementsbyclassname-vs-queryselectorall/18
我发现了这个:https: //jsperf.com/getelementsbyclassname-vs-queryselectorall/18
It runs a test on the 2 x examples above, plus it chucks in a test for jQuery's equivalent selector as well. my test results were as follows:
它在上面的 2 x 示例上运行测试,此外它还对 jQuery 的等效选择器进行了测试。我的测试结果如下:
getElementsByClassName = 1,138,018 operations / sec - <<< clear winner
querySelectorAll = 39,033 operations / sec
jquery select = 381,648 operations / sec
回答by algorhythm
querySelectorcan be a complete CSS(3)-Selector with IDs and Classes and Pseudo-Classes together like this:
querySelector可以是一个完整的 CSS(3)-Selector,其中包含 ID、类和伪类,如下所示:
'#id.class:pseudo'
// or
'tag #id .class .class.class'
with getElementByClassNameyou can just define a class
与getElementByClassName你可以定义一个类
'class'
with getElementByIdyou can just define an id
与getElementById你可以定义一个id
'id'
回答by Jan Han?i?
querySelectorand querySelectorAllare a relatively new APIs, whereas getElementByIdand getElementsByClassNamehave been with us for a lot longer. That means that what you use will mostly depend on which browsers you need to support.
querySelector和querySelectorAll是一个相对较新的 API,而getElementById和 getElementsByClassName已经与我们一起使用了很长时间。这意味着您使用的内容主要取决于您需要支持的浏览器。
As for the :, it has a special meaning so you have to escape it if you have to use it as a part of a ID/class name.
至于:,它具有特殊含义,因此如果您必须将其用作 ID/类名称的一部分,则必须将其转义。
回答by Ambuj Khanna
Difference between "querySelector" and "querySelectorAll"
“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>
回答by mzoz
querySelectoris of w3c Selector API
querySelector是 w3c选择器 API
getElementByis of w3c DOM API
getElementBy是 w3c DOM API
IMO the most notable difference is that the return type of querySelectorAllis a static node list and for getElementsByit's a live node list. Therefore the looping in demo 2 never ends because lisis live and updates itself during each iteration.
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"));
}
回答by Багдаулет Сайын
look at this
看这个
https://codepen.io/bagdaulet/pen/bzdKjL
getElementById fastest than querySelector on 25%
getElementById 比 querySelector 快 25%
jquery is slowest
jquery 是最慢的
var q = time_my_script(function() {
for (i = 0; i < 1000000; i++) {
var w = document.querySelector('#ll');
}
});
console.log('querySelector: '+q+'ms');

