querySelectorAll和getElementsBy *方法返回什么?


151

getElementsByClassName(以及类似的功能,例如getElementsByTagNamequerySelectorAll)与getElementById,还是他们返回元素的数组?

我问的原因是因为我试图使用更改所有元素的样式getElementsByClassName。见下文。

//doesn't work
document.getElementsByClassName('myElement').style.size = '100px';

//works
document.getElementById('myIdElement').style.size = '100px';

37
线索的名称非常多:getElementsByClassName()表示复数,而getElementById()表示单数元素项。
大卫说,恢复莫妮卡(Monica)

1
我明白了,对于我来说,您不能使用上面的代码更改具有该类名称的所有元素,而不必遍历数组。jQuery的方法要好得多,我只是对JS的方法感到好奇
dmo 2012年

Answers:


152

您的getElementById()代码可以正常工作,因为ID必须是唯一的,因此该函数始终只返回一个元素(或null如果找不到任何)。

然而,getElementsByClassName()querySelectorAll(),和其他getElementsBy*方法返回元件的阵列状的集合。像使用真实数组那样对其进行迭代:

var elems = document.getElementsByClassName('myElement');
for(var i = 0; i < elems.length; i++) {
    elems[i].style.size = '100px';
}

如果您喜欢较短的内容,请考虑使用jQuery

$('.myElement').css('size', '100px');

1
这是否也适用于<iframe>您的域的一部分
JMASTER B

3
现在是2018年...只需为其创建包装函数querySelectorAll(),您就可以拥有不错的短代码,而无需使用大量的老式依赖。qSA(".myElement").forEach(el => el.style.size = "100px")也许让包装器收到回调。qSA(".myElement", el => el.style.size = "100px")

2
“如果您希望使用更短的内容,请考虑向您的项目中添加一个巨大的库。”我知道2012年是一个不同的时代,但是即使那样,我仍然觉得这有点荒谬。
CoryCoolguy

1
就像在真实数组上那样对其进行迭代……小心,getElementsByClassName返回一个活动的 NodeList,它可能在循环过程中被意外修改,例如,如果删除了它们所选择的类名。;-)
RobG,

20

您使用的阵列为对象,之间的差getElementbyIdgetElementsByClassName是:

  • getElementbyId将返回Element对象;如果未找到具有ID的元素,则返回null
  • getElementsByClassName将返回一个实时HTMLCollection,如果找不到匹配的元素,则长度可能为0

getElementsByClassName

getElementsByClassName(classNames)方法采用一个字符串,该字符串包含无序的一组唯一的,用空格分隔的表示类的标记。调用该方法时,该方法必须返回一个实时NodeList对象,该 对象包含文档中具有该参数指定的所有类的所有元素,并已通过在空格上拆分字符串来获得了这些类。如果在参数中未指定标记,则该方法必须返回一个空的NodeList。

https://www.w3.org/TR/2008/WD-html5-20080610/dom.html#getelementsbyclassname

getElementById

getElementById()方法访问具有指定ID的第一个元素。

https://developer.mozilla.org/zh-CN/docs/Web/API/Document/getElementById

在您的代码行:

1- document.getElementsByClassName('myElement')。style.size ='100px';

不会按预期方式工作,因为getElementByClassName会返回一个数组,并且该数组将具有该style属性,因此您可以element通过遍历它们来访问每个属性。

这就是该函数getElementById为您工作的原因,该函数将返回直接对象。因此,您将能够访问该style属性。


请注意,由浏览器实现的whatwg规范与此处的w3c 规范确实有所不同,前者(以及当前的浏览器)返回的是getElementsByClassName的HTMLCollection,而不是NodeList的HTMLCollection。轻微,但可能会混淆一些。
Kaiido

@Kaiido —实际的区别是……?据我了解,NodeList是DOM元素的通用集合,可以在任何DOM中使用,而不仅仅是HTML DOM(例如XML DOM),而HTMLCollection用于HTML DOM(显然)。我能看到的唯一区别是namedItem的方法的HTMLCollection
RobG

PS Nit选择:WHATWG HTML Living标准W3C HTML 5.2标准的链接。被选择宠坏了。;-)与您提出的观点没有区别。
RobG

@RobG NodeList有许多 HTMLCollection 上无法访问的方法
海伊多

@Kaiido —可以肯定,但是W3C或WHATWG并未将forEach指定为集合或NodeList的接口的一部分,而是将其分别指定,例如,作为Web IDL规范中通用集合的属性,因此应同时应用于集合和NodeLists (尽管我接受您的观点,即getElementsByClassName返回的集合没有forEach方法)。我想最重要的是,有足够的故事可以讲一个好的答案。:-)
RobG

11

以下描述来自此页面

getElementsByClassName()方法以NodeList对象的形式返回文档中具有指定类名的所有元素的集合。

NodeList对象代表节点的集合。可以通过索引号访问节点。索引从0开始。

提示:可以使用NodeList对象的length属性来确定具有指定类名的元素的数量,然后可以遍历所有元素并提取所需的信息。

因此,作为参数 getElementsByClassName将接受类名称。

如果这是您的HTML正文:

<div id="first" class="menuItem"></div>
<div id="second" class="menuItem"></div>
<div id="third" class="menuItem"></div>
<div id="footer"></div>

然后var menuItems = document.getElementsByClassName('menuItem')将返回3个高位的集合(不是数组)<div>的,因为它们与给定的类名匹配。

然后,您可以使用以下方法遍历此节点(<div>在本例中为)的集合:

for (var menuItemIndex = 0 ; menuItems.length ; menuItemIndex ++) {
   var currentMenuItem = menuItems[menuItemIndex];
   // do stuff with currentMenuItem as a node.
}

有关元素和节点之间的区别,请参考这篇文章


11

ES6提供Array.from()了从类似数组或可迭代对象的对象创建新Array实例的方法。

let boxes = document.getElementsByClassName('box');

Array.from(boxes).forEach(v => v.style.background = 'green');
console.log(Array.from(boxes));
.box {
  width: 50px;
  height: 50px;
  margin: 5px;
  background: blue;
  display: inline-block;
}
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>

正如您在代码片段中看到的那样,使用Array.from()函数之后,您便可以操纵每个元素。


使用相同的解决方案jQuery

$('.box').css({'background':'green'});
.box {
  width: 50px;
  height: 50px;
  margin: 5px;
  background: blue;
  display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>


7

换一种说法

  • document.querySelector()仅选择指定选择器的第一个元素。因此它不会吐出一个数组,它是一个值。类似于document.getElementById()仅获取ID元素,因为ID必须是唯一的。

  • document.querySelectorAll()使用指定的选择器选择所有元素,然后将它们返回到数组中。与仅document.getElementsByClassName()适用于类和document.getElementsByTagName()标签相似。


为什么要使用querySelector?

它仅用于轻松和简洁的目的。


为什么要使用getElement / sBy?*

性能更快。


为什么会有这种性能差异?

两种选择的目的都是为了创建NodeList以便进一步使用。 querySelectors使用选择器生成一个静态NodeList,因此必须首先从头开始创建它。
getElement / sBy *立即适应当前DOM的现有活动NodeList。

因此,何时使用哪种方法取决于您/您的项目/您的设备。


资讯

所有方法的演示
NodeList文档
性能测试


4

它返回类似数组的列表。

您以一个数组为例

var el = getElementsByClassName("elem");
el = Array.prototype.slice.call(el); //this line
el[0].appendChild(otherElem);  

4

您可以通过运行获得一个元素

document.querySelector('.myElement').style.size = '100px';

但它将适用于类.myElement的第一个元素。

如果您想将此内容应用于类的所有元素,建议您使用

document.querySelectorAll('.myElement').forEach(function(element) {
    element.style.size = '100px';
});

4
/*
 * To hide all elements with the same class, 
 * use looping to reach each element with that class. 
 * In this case, looping is done recursively
 */

const hideAll = (className, i=0) => {
if(!document.getElementsByClassName(className)[i]){ //exits the loop when element of that id does not exist
  return; 
}

document.getElementsByClassName(className)[i].style.visibility = 'hidden'; //hide element
return hideAll(className, i+1) //loop for the next element
}

hideAll('appBanner') //the function call requires the class name


0

Drenzii的具体情况的答案 ...

您可以创建一个对任何word元素都适用的函数,并传递要转换元素的编号,例如:

// Binds `wordButtons` to an (array-like) HTMLCollection of buttons
const wordButtons = document.getElementsByClassName("word");

// Applies the `slantWord` function to the first word button
slantWord(1);

// Defines the `slantWord` function
function slantWord(wordNumber) {
  const index = wordNumber - 1; // Collection index is zero-based
  wordButtons[index].style.transform = "rotate(7deg)"; // Transforms the specified button
}
<div class="wordGameContainer">
  <button class="word word1">WORD 1</button>
  <button class="word word2">WORD 2</button>
  <button class="word word3">WORD 3</button>
  <button class="word word4">WORD 4</button>
</div>

<div>
  <button onclick="moveWord()" class="playButton">PLAY</button>
</div>

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.