JS:使用Array.forEach迭代getElementsByClassName的结果

时间:2010-10-06 10:28:04

标签: javascript 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数组的结果是?如果没有,那是什么?

11 个答案:

答案 0 :(得分:279)

没有。作为specified in DOM4,它是HTMLCollection(在现代浏览器中,至少。较旧的浏览器返回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) {...});

如果您处于能够使用ES6的幸福位置(即您可以放心地忽略Internet Explorer或使用ES5转换程序),则可以使用Array.from

Array.from(els).forEach((el) => {
    // Do stuff here
    console.log(el.tagName);
});

答案 1 :(得分:55)

您可以使用'44'将集合转换为数组,这比Array.from更清晰:

Array.prototype.forEach.call

在不支持Array.from(document.getElementsByClassName("myclass")).forEach( function(element, index, array) { // do stuff } ); 的旧浏览器中,您需要使用像Babel这样的内容。

ES6还添加了这种语法:

Array.from

使用[...document.getElementsByClassName("myclass")].forEach( (element, index, array) => { // do stuff } ); 进行休息解构可以处理所有类似数组的对象,而不仅仅是数组本身,然后使用旧的数组语法从值构造数组。

虽然替代函数...(使querySelectorAll过时)返回一个本身具有getElementsByClassName的集合,但其他方法如forEachmap缺少,所以这种语法仍然有用:

filter

答案 2 :(得分:15)

或者您可以使用返回NodeListquerySelectorAll

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

现代浏览器支持(包括Edge,但不支持IE):
Can I use querySelectorAll
NodeList.prototype.forEach()

MDN: Document.querySelectorAll()

答案 3 :(得分:13)

编辑:虽然新版本的HTML中的返回类型已更改(请参阅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。

答案 4 :(得分:5)

  

getElementsByClassName的结果是否为数组?

没有

  

如果没有,那是什么?

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

答案 5 :(得分:5)

getElementsByClassName()的结果不是数组,而是类数组对象。具体来说,它被称为HTMLCollection,不要与NodeListwhich has it's own forEach() method)混淆。

使用ES2015转换类似数组的对象以便与Array.prototype.forEach()一起使用尚未提及的一种简单方法是使用扩展运算符或spread syntax

const elementsArray = document.getElementsByClassName('myclass');

[...elementsArray].forEach((element, index, array) => {
    // do something
});

答案 6 :(得分:3)

如上所述,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语言绑定中,是一个接口     iterable将具有“entries”,“forEach”,“keys”,“values”和     @@iterator上的interface prototype object属性。

  

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

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

请注意,目前尚未得到广泛支持。另请参阅forEach method of Node.childNodes?

答案 7 :(得分:0)

它不返回Array,而是返回NodeList

答案 8 :(得分:0)

这是更安全的方法:

var elements = document.getElementsByClassName("myclass");
for (var i = 0; i < elements.length; i++) myFunction(elements[i]);

答案 9 :(得分:0)

getElementsByClassName在现代浏览器中返回 HTMLCollection

这是 类似于自变量的类似于数组的对象,可以通过for...of循环对其进行迭代,请参见下面的MDN文档所说的内容:

  

for ... of语句创建一个循环遍历可迭代对象,   包括:内置String,Array,类似数组的对象(例如,参数   或NodeList),TypedArray,Map,Set和用户定义的可迭代对象。它   调用一个自定义迭代钩子,该钩子要为   对象的每个不同属性的值。

示例

for (let element of getElementsByClassName("classname")){
   element.style.display="none";
}

答案 10 :(得分:0)

这是我在jsperf上创建的测试: https://jsperf.com/vanillajs-loop-through-elements-of-class

Chrome和Firefox中性能最好的版本是结合document.getElementsByClassName的旧版本for循环:

var elements = document.getElementsByClassName('testClass'), elLength = elements.length;
for (var i = 0; i < elLength; i++) {
    elements.item(i).textContent = 'Tested';
};

在Safari中,这种变体是赢家:

var elements = document.querySelectorAll('.testClass');
elements.forEach((element) => {
    element.textContent = 'Tested';
});

如果您想让所有浏览器都拥有最出色的性能,那就可能是这样:

var elements = document.getElementsByClassName('testClass');
Array.from(elements).map(
    (element) => {
        return element.textContent = 'Tested';
    }
);