我想知道两者之间到底有什么区别querySelector
and querySelectorAll
反对getElementsByClassName
and getElementById
?
From 这个链接我可以收集到querySelector
我可以写document.querySelector(".myclass")
获取带有类的元素myclass
and document.querySelector("#myid")
获取带有ID的元素myid
。但我已经可以做到了getElementsByClassName
and getElementById
。应该优先选择哪一个?
我也工作于XPages其中 ID 是使用冒号动态生成的,如下所示view:_id1:inputText1
。所以当我写的时候document.querySelector("#view:_id1:inputText1")
它不起作用。但写作document.getElementById("view:_id1:inputText1")
作品。有什么想法吗?
对于这个答案,我参考了querySelector
and querySelectorAll
作为 querySelector* 和getElementById
, getElementsByClassName
, getElementsByTagName
, and getElementsByName
作为 getElement*。
很多这些信息可以在规范中得到验证,其中很多来自我编写规范时运行的各种基准测试。规格:https://dom.spec.whatwg.org/
主要区别
- querySelector* 更加灵活,因为您可以向其传递任何 CSS3 选择器,而不仅仅是简单的 id、标签或类选择器。
- querySelector* 的性能随着调用它的 DOM 的大小而变化。准确地说,querySelector* 调用运行时间为 O(n),而 getElement* 调用运行时间为 O(1),其中 n 是调用它的元素或文档的所有子元素的总数。
- 这些调用的返回类型各不相同。
querySelector
and getElementById
两者都返回单个元素。querySelectorAll
and getElementsByName
两者都返回 NodeList。年龄较大的getElementsByClassName
and getElementsByTagName
两者都返回 HTMLCollections。 NodeList 和 HTMLCollections 都称为元素集合。
- 集合可以分别返回“实时”或“静态”集合。这没有反映在它们返回的实际类型中。 getElements* 调用返回实时集合,而 querySelectorAll 返回静态集合。按照我的理解,实时集合包含对 DOM 中元素的引用,静态集合包含元素的副本。从不同的角度也可以看看下面 @Jan Feldmann 的评论。我还没有找到将其纳入我的答案的好方法,但这可能是更准确的理解。
下表总结了这些概念。
Function | Live? | Type | Time Complexity
querySelector | | Element | O(n)
querySelectorAll | N | NodeList | O(n)
getElementById | | Element | O(1)
getElementsByClassName | Y | HTMLCollection | O(1)
getElementsByTagName | Y | HTMLCollection | O(1)
getElementsByName | Y | NodeList | O(1)
详细信息、提示和示例
-
HTMLCollections 不像 NodeLists 那样像数组,并且不支持 .forEach()。我发现扩展运算符对于解决这个问题很有用:
[...document.getElementsByClassName("someClass")].forEach()
-
每个元素和全局document
,可以访问所有这些功能,除了getElementById
and getElementsByName
,仅在document
.
-
链接 getElement* 调用而不是使用 querySelector* 将提高性能,尤其是在非常大的 DOM 上。即使在小型 DOM 和/或具有很长链的情况下,它通常也会更快。但是,除非您知道需要性能,否则应首选 querySelector* 的可读性。querySelectorAll
通常很难重写,因为您必须在每一步中从 NodeList 或 HTMLCollection 中选择元素。例如,以下代码的作用是not work:
document.getElementsByClassName("someClass").getElementsByTagName("div")
因为您只能对单个元素而不是集合使用 getElements*,但如果您只想要一个元素,那么:
document.querySelector("#someId .someClass div")
可以写成:
document.getElementById("someId").getElementsByClassName("someClass")[0].getElementsByTagName("div")[0]
注意使用[0]
在返回集合的每个步骤中仅获取集合的第一个元素,从而在末尾产生一个元素,就像querySelector
.
-
由于所有元素都可以访问 querySelector* 和 getElement* 调用,因此您可以使用这两个调用来创建链,如果您想要一些性能提升,这可能很有用,但无法避免无法根据 getElement* 调用编写的 querySelector 。
-
虽然通常很容易判断是否可以仅使用 getElement* 调用来编写选择器,但有一种情况可能并不明显:
document.querySelectorAll(".class1.class2")
可以重写为
document.getElementsByClassName("class1 class2")
-
在使用 querySelector* 获取的静态元素上使用 getElement* 将导致一个元素相对于由 querySelector 复制的 DOM 的静态子集而言是活动的,但相对于完整文档 DOM 来说不是活动的......这就是简单的地方对元素的实时/静态解释开始崩溃。您可能应该避免必须担心这一点的情况,但如果您这样做,请记住 querySelector* 在返回对它们的引用之前调用复制它们找到的元素,但 getElement* 调用获取直接引用而不进行复制。
-
查询选择器* 和getElementById
以前序、深度优先的方式遍历元素,在规范中称为“树顺序”。对于其他 getElement* 调用,我从规范中不清楚 - 它们可能与树顺序相同,但是getElementsByClassName(".someClass")[0]
可能无法在每个浏览器中可靠地给出相同的结果。getElementById("#someId")
即使您的页面上有同一 ID 的多个副本,也应该如此。
-
当我不得不研究这个问题时,我正在开发一个无限滚动页面,我认为这可能是性能成为问题的常见情况。我们的代码有 onScroll 事件,其中包含 querySelectorAll 调用。即使调用受到速率限制,如果您向下滚动得足够远,页面也会中断,此时将会有太多的调用迭代太多的元素,导致浏览器无法跟上。 DOM 的大小与此用例相关,因此在无限滚动页面上运行的代码中最好选择 getElement* 调用。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)