JavaScript中的querySelector和querySelectorAll vs getElementsByClassName和getElementById

时间:2013-01-17 11:00:20

标签: javascript

我想知道querySelectorquerySelectorAllgetElementsByClassNamegetElementById的区别究竟是什么?

来自this link我可以通过querySelector来收集document.querySelector(".myclass")我可以写myclass来获取类document.querySelector("#myid")myid的元素来获取ID为{{{1}的元素1}}。但我已经可以getElementsByClassNamegetElementById。应该首选哪一个?

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

11 个答案:

答案 0 :(得分:86)

  

我想知道querySelector和querySelectorAll对getElementsByClassName和getElementById的区别究竟是什么?

语法和浏览器支持。

当您想要使用更复杂的选择器时,

querySelector会更有用。

e.g。所有列表项都来自作为foo类成员的元素:.foo li

  

document.querySelector(“#view:_id1:inputText1”)它不起作用。但是编写document.getElementById(“view:_id1:inputText1”)可以正常工作。有什么想法吗?

:字符在选择器中具有特殊含义。你必须逃脱它。 (选择器转义字符在JS字符串中也有特殊含义,所以你必须转义那个)。

document.querySelector("#view\\:_id1\\:inputText1")

答案 1 :(得分:80)

Mozilla Documentation:收集

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

<强> querySelector

  

返回节点子树中的第一个匹配的Element节点。如果   找不到匹配的节点,返回null。

<强> querySelectorAll

  

返回包含所有匹配的Element 节点的 NodeList   节点的子树,如果没有找到匹配,则为空的NodeList。

  

注意:querySelectorAll()返回的NodeList不是活动的,这是   表示DOM中的更改未反映在集合中。   这与返回实时的其他DOM查询方法不同   节点列表。

答案 2 :(得分:65)

关于差异,querySelectorAllgetElementsByClassName之间的结果中存在重要差异:返回值不同。 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>

答案 3 :(得分:16)

querySelector可以是一个完整的CSS(3) - 具有ID和类以及伪类的选择器,如下所示:

'#id.class:pseudo'

// or

'tag #id .class .class.class'

使用getElementByClassName,您只需定义一个类

即可
'class'

getElementById你可以定义一个id

'id'

答案 4 :(得分:14)

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

querySelector / querySelectorAll or getElementsByClassName

我发现了这个: https://jsperf.com/getelementsbyclassname-vs-queryselectorall/18

它对上面的2个示例进行了测试,并且还测试了jQuery的等效选择器。我的测试结果如下:

getElementsByClassName = 1,138,018 operations / sec - <<< clear winner
querySelectorAll = 39,033 operations / sec
jquery select = 381,648 operations / sec

答案 5 :(得分:7)

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

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

答案 6 :(得分:5)

对于此答案,我将querySelectorquerySelectorAll称为querySelector *,并将getElementByIdgetElementsByClassNamegetElementsByTagNamegetElementsByName称为作为getElement *。

主要区别

  1. querySelector *更加灵活,因为您可以将任何CSS3选择器传递给它,而不仅仅是ID,标记或类的简单选择器。
  2. querySelector *的性能随调用的DOM的大小而变化。确切地说,querySelector *调用在O(n)时间运行,而getElement *调用在O(n)时间运行1)时间,其中n是被调用的元素或文档的所有子元素的总数。这个事实似乎鲜为人知,因此我将其加粗。
  3. getElement *调用返回对DOM的直接引用,而querySelector *在内部将选定元素的副本复制回DOM之前。这些被称为“活动”和“静态”元素。这与它们返回的类型并不严格相关。我无法知道以编程方式确定元素是处于活动状态还是静态状态,因为它取决于元素是否在某个时刻被复制,并且不是数据的固有属性。对活动元素的更改将立即应用-更改活动元素会直接在DOM中对其进行更改,因此JS的下一行可以看到该更改,并且该更改会传播到立即引用该元素的任何其他活动元素。对静态元素的更改仅在当前脚本执行完成后才写回到DOM。这些额外的复制和写入步骤对性能的影响很小,通常可以忽略不计。
  4. 这些调用的返回类型各不相同。 querySelectorgetElementById都返回一个元素。 querySelectorAllgetElementsByName都返回NodeLists,它们是HTMLCollection过时后添加的较新函数。较旧的getElementsByClassNamegetElementsByTagName都返回HTMLCollections。再次,这本质上与元素是活动的还是静态的无关。

这些概念总结在下表中。

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)

详细信息,技巧和示例

  • HTMLCollections不像NodeLists那样像数组,并且不支持.forEach()。我发现散布运算符对于解决此问题很有帮助:

    [...document.getElementsByClassName("someClass")].forEach()]

  • 每个元素和全局document都可以访问所有这些功能,但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]来获取集合的第一个元素,与querySelector一样,最后使用一个元素。

    < / li>
  • 由于所有元素都可以访问querySelector *和getElement *调用,因此可以使用这两个调用建立链,如果希望获得一些性能提升,这将很有用,但不能避免无法写入的querySelector getElement *调用的条款。

  • 虽然通常很容易判断是否只能使用getElement *调用编写选择器,但是有一种情况可能并不明显:

    document.querySelectorAll(".class1.class2")

    可以改写为

    document.getElementsByClassName("class1 class2")

  • 在通过querySelector *获取的静态元素上使用getElement *会导致一个元素相对于querySelector复制的DOM的静态子集处于活动状态,而相对于整个文档DOM不起作用。在这里,简单的动态/静态元素解释开始瓦解。您可能应该避免这种情况,但如果这样做,请记住,querySelector *会在返回对它们的引用之前调用它们找到的复制元素,但是getElement *会调用直接引用而不进行复制。

  • 如果存在多个匹配项,则两个API都不指定应首先选择哪个元素。

  • 因为querySelector遍历DOM直到找到匹配项,以上内容还意味着您不能依靠要在DOM中寻找的元素的位置来优化性能-浏览器可能向后,向前,深度优先,广度优先或任何喜欢的方式遍历DOM。

答案 7 :(得分: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>

答案 8 :(得分:3)

querySelector是w3c Selector 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")); 
}

答案 9 :(得分: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');

答案 10 :(得分:-1)

querySelector和getlementbyID(Claassname,Tagname等)之间的主要区别是,如果有多个元素满足条件,则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.

如果要为queryslector选择单个元素,或者要为getElement选择多个元素,则简短