JS:使用Array.forEach遍历getElementsByClassName的结果
我想迭代一些DOM元素,我这样做:
document.getElementsByClassName( "myclass" ).forEach( function(element, index, array) { //do stuff });
但我得到一个错误:document.getElementsByClassName(“myclass”)forEach不是一个函数
我正在使用Firefox 3,所以我知道getElementsByClassName
和Array.forEach
都存在。 这工作正常:
[2, 5, 9].forEach( function(element, index, array) { //do stuff });
getElementsByClassName
是Array的结果吗? 如果不是,那是什么?
不行 。 按照DOM4的规定 ,这是一个HTMLCollection
(在现代浏览器中,至less老版本的浏览器返回了一个NodeList
)。
在所有现代浏览器(几乎所有其他IE <= 8)中,您可以调用Array的forEach
方法,并将它的元素列表( HTMLCollection
或NodeList
)作为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 。