JS:使用Array.forEach遍历getElementsByClassName的结果

我想迭代一些DOM元素,我这样做:

document.getElementsByClassName( "myclass" ).forEach( function(element, index, array) { //do stuff }); 

但我得到一个错误:document.getElementsByClassName(“myclass”)forEach不是一个函数

我正在使用Firefox 3,所以我知道getElementsByClassNameArray.forEach都存在。 这工作正常:

 [2, 5, 9].forEach( function(element, index, array) { //do stuff }); 

getElementsByClassName是Array的结果吗? 如果不是,那是什么?

不行 。 按照DOM4的规定 ,这是一个HTMLCollection (在现代浏览器中,至less老版本的浏览器返回了一个NodeList )。

在所有现代浏览器(几乎所有其他IE <= 8)中,您可以调用Array的forEach方法,并将它的元素列表( HTMLCollectionNodeList )作为this值传递给它:

 var els = document.getElementsByClassName("myclass"); Array.prototype.forEach.call(els, function(el) { // Do stuff here console.log(el.tagName); }); // Or [].forEach.call(els, function (el) {...}); 

编辑:虽然新版本的HTML中返回types已经改变(请参阅Tim Down的更新答案),但下面的代码仍然有效。

正如其他人所说,这是一个NodeList。 下面是一个完整的工作示例,您可以尝试:

 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script> function findTheOddOnes() { var theOddOnes = document.getElementsByClassName("odd"); for(var i=0; i<theOddOnes.length; i++) { alert(theOddOnes[i].innerHTML); } } </script> </head> <body> <h1>getElementsByClassName Test</h1> <p class="odd">This is an odd para.</p> <p>This is an even para.</p> <p class="odd">This one is also odd.</p> <p>This one is not odd.</p> <form> <input type="button" value="Find the odd ones..." onclick="findTheOddOnes()"> </form> </body> </html> 

这适用于Win 7上的IE 9,FF 5,Safari 5和Chrome 12。

您可以使用Array.from将集合转换为数组:

 Array.from(document.getElementsByClassName("myclass")).forEach( function(element, index, array) { //do stuff } ); 

我认为它比Array.prototype.forEach.call更清洁。

(在不支持Array.from旧版浏览器中,您可能需要使用像Babel这样的东西。)

或者你可以使用querySelectorAll返回NodeList :

 document.querySelectorAll('.myclass').forEach(...) 

现代浏览器支持(包括Edge,但不支持IE):
我可以使用querySelectorAll吗?
NodeList.prototype.forEach()

MDN: Document.querySelectorAll()

getElementsByClassName是Array的结果吗?

没有

如果不是,那是什么?

和所有返回多个元素的DOM方法一样,它是一个NodeList,参见https://developer.mozilla.org/en/DOM/document.getElementsByClassName

如前所述, getElementsByClassName返回一个HTMLCollection ,它被定义为

 [Exposed=Window] interface HTMLCollection { readonly attribute unsigned long length ; getter Element ? item (unsigned long index ); getter Element ? namedItem (DOMString name ); }; 

以前,一些浏览器改为返回一个NodeList

 [Exposed=Window] interface NodeList { getter Node ? item (unsigned long index ); readonly attribute unsigned long length ; iterable< Node >; }; 

区别很重要,因为DOM4现在将NodeList定义为可迭代的。

根据Web IDL草案,

实现被声明为可迭代的接口的对象支持被迭代以获得一系列值。

注意 :在ECMAScript语言绑定中,可迭代的接口将在其接口原型对象上具有“entries”,“forEach”,“keys”,“values”和@@ iterator属性。

这意味着,如果您想使用forEach ,则可以使用返回NodeList的DOM方法,如querySelectorAll

 document.querySelectorAll(".myclass").forEach(function(element, index, array) { // do stuff }); 

注意这还没有得到广泛的支持。 另请参阅forEach方法Node.childNodes?

getElementsByClassName()的结果不是一个数组,而是一个类似数组的对象 。 特别是它被称为HTMLCollection ,不要与NodeList ( 它有自己的forEach()方法 )混淆。

使用ES2015来转换类似Array.prototype.forEach()的类似数组的对象的一个​​简单方法就是使用扩展运算符或扩展语法 :

 const elementsArray = document.getElementsByClassName('myclass'); [...elementsArray].forEach((element, index, array) => { // do something }); 

它不返回一个Array ,它返回一个NodeList 。