JavaScript 中的 querySelector 和 querySelectorAll 与 getElementsByClassName 和 getElementById

2023-11-22

我想知道两者之间到底有什么区别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/

主要区别

  1. querySelector* 更加灵活,因为您可以向其传递任何 CSS3 选择器,而不仅仅是简单的 id、标签或类选择器。
  2. querySelector* 的性能随着调用它的 DOM 的大小而变化。准确地说,querySelector* 调用运行时间为 O(n),而 getElement* 调用运行时间为 O(1),其中 n 是调用它的元素或文档的所有子元素的总数。
  3. 这些调用的返回类型各不相同。querySelector and getElementById两者都返回单个元素。querySelectorAll and getElementsByName两者都返回 NodeList。年龄较大的getElementsByClassName and getElementsByTagName两者都返回 HTMLCollections。 NodeList 和 HTMLCollections 都称为元素集合。
  4. 集合可以分别返回“实时”或“静态”集合。这没有反映在它们返回的实际类型中。 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(使用前将#替换为@)

JavaScript 中的 querySelector 和 querySelectorAll 与 getElementsByClassName 和 getElementById 的相关文章

随机推荐

  • 带有符号链接的 mod_xsendfile

    我在 Rails 3 应用程序中使用 xsendfile 时遇到问题 我使用 capistrano 来管理部署 在每个版本中 都有一个指向共享 资产目录的符号链接 例如 var www site releases 1234 assets g
  • 部署应用程序引擎应用程序时如何处理敏感配置信息?

    示例 我有一个应用程序需要访问提供身份验证令牌的 API myApi MyApi token my private sensible token 我想避免在属于项目一部分的配置文件中包含该私有令牌 我想到的一个解决方案是在一个单独的代理应用
  • 当Java自动更新时更新Windows路径变量?

    这个问题询问如何在 Windows 中设置路径变量以包含 Java bin 目录 从而允许您在提示符下使用 javac 命令 针对此问题发布的解决方案指出您应该对最新 Java 安装的绝对路径进行硬编码 在这种情况下 它恰好是c progr
  • 如何在不同的包中使用两个同名的类? [复制]

    这个问题在这里已经有答案了 如何访问不同包中具有相同名称的两个类 foo bar myClass class and foo myClass class 所有这些都在同一个班级中 TestRunner Suite class SuiteTe
  • 使用 pgAdmin 进行远程 PostgreSQL 连接

    我正在尝试通过基于 Ubuntu 16 04 的服务器上运行的 PostgreSQL 建立远程连接 到目前为止 当我单击 pgAdmin 上的 保存 按钮时 它有点冻结 什么也不做 输入 manage py runserver My dro
  • 处理 BeautifulSoup CSS 选择器中的冒号

    输入 HTML div style display flex div class half style font size 6 width 33 apple div div class half style font size 6 text
  • iOS Swift,Enum CaseIterable 扩展

    我正在尝试为枚举编写一个扩展CaseIterable这样我就可以获得原始值的数组而不是案例 但我并不完全确定如何做到这一点 extension CaseIterable static var allValues String get ret
  • Parcelable 中的 Parcel 读/写操作时变量顺序是否重要?

    我有以下实现Parcelable class public class DemoModel implements Parcelable private String para1 private int para2 public DemoMo
  • 在 T-SQL 中使用环境变量

    如何在 T SQL 脚本中读取系统环境变量的值 这是在 SQL Server 2005 上运行 要 读取 T SQL 脚本中系统环境变量的值 您可以将 SQL Management Studio 设置为使用 sqlcmd 模式 然后你可以像
  • Shell脚本:如何删除目录中除文件中列出的文件之外的所有文件?

    我有一个目录 temp 包含许多文件和子目录 并且在某些目录中 可能还包含其他文件和子目录 另外 在目录 temp 它包含一个特殊的txt文件 名为kept txt 它列出了其中包含的一些直接文件和子目录 temp 现在我想删除下面的所有其
  • Rails 4 中的左外连接

    我有3个型号 class Student lt ActiveRecord Base has many student enrollments dependent destroy has many courses through studen
  • 自引用外键约束和删除

    在 SQL Server 中处理自引用外键约束的推荐方法是什么 桌子型号 fiData引用 tabData 中的先前记录 如果我删除引用的记录fiData 数据库抛出异常 DELETE 语句与 SAME TABLE REFERENCE 冲突
  • 在边框半径图像背景上添加边框渗透

    我在蓝色背景的图像上添加黑色边框 这样做时 似乎在边框内部添加了非常明显的背景彩色轮廓 有办法摆脱这个吗 我使用的代码很简单 border radius 100 border 3px solid rgb 0 0 0 您可以通过向任何图像添加
  • 如何让匿名用户编辑 Google Drive Realtime 文档?

    我想创建一个网页 使用Google 云端硬盘实时 API允许用户匿名编辑多个文本字段 由于可能有多个用户同时访问该页面 因此我想防止某人的编辑被另一个用户覆盖 而第一个编辑者不知道他的编辑已被覆盖 然而 从快速开始 似乎需要使用 Googl
  • 如何在pandas中按列表删除行[重复]

    这个问题在这里已经有答案了 现在我有数据框和列表 A B 1 a 2 b 3 c 4 d 5 e list a b c 我想通过 df B 引用列表来删除行 我想在下面 df A B 4 d 5 e 我怎样才能得到这个结果 您可以使用isi
  • imghdr / python - 无法检测某些图像的类型(图像扩展)

    我正在使用 Python 脚本从 imgur com 下载大量图像 因为我拥有该格式的所有链接http imgur com id 我必须通过将原始网址替换为来强制下载它们http i imgur com id gif 然后保存所有图像 不带
  • 如何使 Matter.js 的最小示例工作?

    我正在尝试使用Matter js 物理库 我正在使用他们的 入门 教程 但找不到画布 这是我的html
  • 分析线程同步锁争用

    过去 我使用过 nprof Equatec profiler 和 Yourkit profiler 等性能分析工具来识别和消除 减少主要 在一个线程 串行执行 中运行的代码中的性能瓶颈 现在我写了很多多线程代码 这些代码会因为锁争用而减慢速
  • 在 PowerShell 中从内存中删除类

    我创建了一个名为 Application 的类 并将其加载到我的主脚本中 Import Module NAME C PowerShell Scripts Class Application ps1 GLOBAL FORCE 但是如果我ONL
  • JavaScript 中的 querySelector 和 querySelectorAll 与 getElementsByClassName 和 getElementById

    我想知道两者之间到底有什么区别querySelector and querySelectorAll反对getElementsByClassName and getElementById From 这个链接我可以收集到querySelecto