223

我想知道querySelectorquerySelectorAll反对 getElementsByClassName和之间到底有什么区别getElementById

这个链接我可以收集到,querySelector我可以写document.querySelector(".myclass")来获取带有 class 的元素myclassdocument.querySelector("#myid")获取带有 ID 的元素myid。但我已经可以做到这一点getElementsByClassName并且getElementById. 应该首选哪一个?

我也在XPages中工作,其中 ID 是用冒号动态生成的,看起来像这样view:_id1:inputText1。所以当我写document.querySelector("#view:_id1:inputText1")它不起作用。但写作document.getElementById("view:_id1:inputText1")有效。任何想法为什么?

4

11 回答 11

159

对于这个答案,我将querySelectorandquerySelectorAll称为 querySelector* 和 to getElementByIdgetElementsByClassNamegetElementsByTagNamegetElementsByNamegetElement*。

很多这些信息都可以在规范中得到验证,其中很多来自我编写它时运行的各种基准测试。规范:https ://dom.spec.whatwg.org/

主要区别

  1. querySelector* 更加灵活,因为您可以将任何 CSS3 选择器传递给它,而不仅仅是用于 id、标签或类的简单选择器。
  2. querySelector* 的性能随调用它的 DOM 的大小而变化。准确地说,querySelector* 调用在 O(n) 时间内运行,而 getElement* 调用在 O(1) 时间内运行,其中 n 是调用它的元素或文档的所有子元素的总数。这个事实似乎是最不为人所知的,所以我将其加粗。
  3. 这些调用的返回类型各不相同。querySelector并且getElementById都返回一个元素。querySelectorAll并且getElementsByName都返回 NodeLists。较旧的getElementsByClassNamegetElementsByTagName两者都返回 HTMLCollections。NodeLists 和 HTMLCollections 都被称为元素的集合。
  4. 集合可以包含对 DOM 中元素的引用或元素的副本。getElement* 调用返回引用集合,而 querySelectorAll 结果包含元素的副本。这些分别称为“实时”和“静态”集合。这与它们返回的类型无关。

下表总结了这些概念。

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和之外的所有这些功能getElementsByName,它们仅在 上实现document

  • 链接 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* 调用获取直接引用而不复制。

  • querySelector* 并按getElementById前序、深度优先遍历元素,在规范中称为“树序”。对于其他 getElement* 调用,我从规范中不清楚 - 它们可能与树顺序相同,但getElementsByClassName(".someClass")[0]可能无法在每个浏览器中可靠地给出相同的结果。getElementById("#someId")但是,即使您的页面上有相同 id 的多个副本,也应该这样做。

于 2019-02-22T03:26:39.963 回答
135

我想知道 querySelector 和 querySelectorAll 与 getElementsByClassName 和 getElementById 之间到底有什么区别?

语法和浏览器支持。

querySelector当您想使用更复杂的选择器时更有用。

例如,所有列表项都来自作为 foo 类成员的元素:.foo li

document.querySelector("#view:_id1:inputText1") 它不起作用。但是写 document.getElementById("view:_id1:inputText1") 有效。任何想法为什么?

:字符在选择器中具有特殊含义。你必须逃避它。(选择器转义字符在 JS 字符串中也具有特殊含义,因此您也必须对其进行转义

document.querySelector("#view\\:_id1\\:inputText1")
于 2013-01-17T11:01:43.593 回答
119

从Mozilla 文档收集:

NodeSelector 接口 本规范为实现 Document、DocumentFragment 或 Element 接口的任何对象添加了两个新方法:

查询选择器

返回节点子树中的第一个匹配元素节点。如果没有找到匹配的节点,则返回 null。

查询选择器全部

返回包含节点子树中所有匹配元素节点的 NodeList,如果未找到匹配项,则返回空 NodeList。

注意:返回的 NodeListquerySelectorAll()不是 live 的,这意味着 DOM 中的更改不会反映在集合中。这与其他返回活动节点列表的 DOM 查询方法不同。

于 2014-11-05T12:49:49.523 回答
96

querySelectorAll关于差异,在and之间的结果中有一个重要的地方getElementsByClassName:返回值不同。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>

于 2016-08-29T18:58:57.487 回答
28

我来到这个页面纯粹是为了找出在性能方面使用更好的方法 - 即更快:

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
于 2017-05-14T19:23:03.280 回答
18

querySelector可以是一个完整的 CSS(3)-Selector,其中包含 ID、类和伪类,如下所示:

'#id.class:pseudo'

// or

'tag #id .class .class.class'

getElementsByClassName你可以定义一个类

'class'

getElementById你可以定义一个id

'id'
于 2013-01-17T11:03:34.297 回答
7

querySelectorquerySelectorAll是一个相对较新的 API,而getElementByIdgetElementsByClassName已经存在了很长时间。这意味着您使用的内容主要取决于您需要支持的浏览器。

至于:,它具有特殊含义,因此如果您必须将其用作 ID/类名的一部分,则必须将其转义。

于 2013-01-17T11:03:06.563 回答
5

querySelector属于 w3c选择器 API

getElementBy属于 w3c DOM API

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")); 
}
于 2018-12-21T06:19:11.237 回答
4

“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>

于 2018-12-01T02:34:23.063 回答
2

看这个

https://codepen.io/bagdaulet/pen/bzdKjL

getElementById 比 querySelector 快 25%

jquery 最慢

var q = time_my_script(function() {

    for (i = 0; i < 1000000; i++) {
         var w = document.querySelector('#ll');
    }

});

console.log('querySelector: '+q+'ms');
于 2019-01-24T06:32:21.627 回答
-3

querySelector 和 getlementbyID(Claassname,Tagname etc) 之间的主要区别在于,如果有多个元素满足条件 querySelector 将仅返回一个输出,而 getElementBy* 将返回所有元素。

让我们考虑一个例子以使其更清楚。

 <nav id="primary" class="menu">
                            <a class="link" href="#">For Business</a>
                            <a class="link" href="#">Become an Instructor</a>
                            <a class="link" href="#">Mobile Applications</a>
                            <a class="link" href="#">Support</a>
                            <a class="link" href="#">Help</a>
   </nav> 

下面的代码将解释差异

**QUERY SELECTOR**
document.querySelector('.link'); // Output : For Business (element)

document.querySelectorAll('.link'); //Out All the element with class link

**GET ELEMENT**
document.getElementsByClassName('link') // Output : will return all the element with a class "link" but whereas in query selector it will return only one element which encounters first.

简而言之,如果我们想为查询选择器选择单个元素,或者如果我们想为 getElement 选择多个元素

于 2019-06-03T18:57:04.523 回答