JavaScript中的querySelector和querySelectorAll vs getElementsByClassName和getElementById

我想知道querySelectorquerySelectorAllgetElementsByClassNamegetElementById之间的确切区别是什么?

这个链接中,我可以用querySelector来收集,我可以写document.querySelector(".myclass")来获取类为myclass的元素,写document.querySelector("#myid")来获取ID为myid的元素。但我已经可以做到getElementsByClassNamegetElementById。应该优先选择哪一种?

我还在XPages中工作,其中ID是动态生成的冒号,看起来像view:_id1:inputText1。所以当我写document.querySelector("#view:_id1:inputText1")时,它不工作。但是编写document.getElementById("view:_id1:inputText1")是可行的。知道为什么吗?

172215 次浏览

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

语法和浏览器支持。

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

例:所有列表项都起源于foo类的成员元素:.foo li

document.querySelector("#view:_id1:inputText1")不起作用。但是写document.getElementById("view:_id1:inputText1")是有效的。知道为什么吗?

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

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

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

至于:,它有一个特殊的含义,所以如果你必须使用它作为ID/类名的一部分,你必须转义它。

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

'#id.class:pseudo'


// or


'tag #id .class .class.class'

使用getElementsByClassName你可以只定义一个类

'class'

使用getElementById你可以只定义一个id

'id'

Mozilla文档:收集

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

querySelector

返回节点子树中的第一匹配元素节点。如果

.如果没有匹配的节点,返回null

querySelectorAll

返回包含所有匹配元素的节点列表节点

.

.

.

而且

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

关于差异,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>

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

querySelector / querySelectorAll or getElementsByClassName

和我发现这个: https://jsperf.com/getelementsbyclassname-vs-queryselectorall/18 < / p >

它在上面的2个x例子上运行了一个测试,另外它还对jQuery的等效选择器进行了测试。我的测试结果如下:

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

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>

querySelector属于w3c 选择器的API

getElementBy属于w3c DOM API

在我看来,最显著的区别是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"));
}

看看这个

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');

对于这个答案,我将querySelectorquerySelectorAll称为querySelector*,将getElementByIdgetElementsByClassNamegetElementsByTagNamegetElementsByName称为getElement*。

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

主要区别

  1. querySelector*更加灵活,因为您可以向它传递任何CSS3选择器,而不仅仅是用于id、标签或类的简单选择器。
  2. querySelector*的性能随着调用它的DOM的大小而变化。准确地说,querySelector*调用在O(n)时间内运行,getElement*调用在O(1)时间内运行,其中n是它所调用的元素或文档的所有子元素的总数。
  3. 这些调用的返回类型各不相同。querySelectorgetElementById都返回一个元素。querySelectorAllgetElementsByName都返回节点列表。旧的getElementsByClassNamegetElementsByTagName都返回HTMLCollections。NodeLists和HTMLCollections都被称为元素的集合。
  4. 收藏可以归还“生活”;或“;static"分别收集。这并没有反映在它们返回的实际类型中。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不像nodelist那样像数组,也不支持. foreach()。我发现展开运算符很有用:

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

  • 每个元素和全局document都可以访问所有这些函数,除了getElementByIdgetElementsByName,它们只在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一样,在最后得到一个元素。

  • 因为所有元素都可以同时访问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的副本。

  • 当我不得不研究这个问题时,我正在研究无限滚动页面,我认为这可能是性能成为问题的常见情况。我们的代码中有onScroll事件和querySelectorAll调用。即使调用有速率限制,如果向下滚动得足够远,页面也会中断,因为此时会有太多调用遍历太多元素,浏览器无法跟上。DOM的大小在这个用例中是相关的,因此在无限滚动页面上运行的代码中更倾向于调用getElement*是一个很好的例子。

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