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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3871547/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 06:26:54  来源:igfitidea点击:

JS: iterating over result of getElementsByClassName using Array.forEach

javascriptforeachgetelementsbyclassname

提问by Steve Claridge

I want to iterate over some DOM elements, I'm doing this:

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

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

but I get an error:

但我收到一个错误:

document.getElementsByClassName("myclass").forEach is not a function

document.getElementsByClassName("myclass").forEach 不是函数

I am using Firefox 3 so I know that both getElementsByClassNameand Array.forEachare present. This works fine:

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

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

Is the result of getElementsByClassNamean Array? If not, what is it?

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

回答by Tim Down

No. As specified in DOM4, it's an HTMLCollection(in modern browsers, at least. Older browsers returned a NodeList).

不。正如在 DOM4 中指定的那样,它是一个HTMLCollection(至少在现代浏览器中。旧浏览器返回一个NodeList)。

In all modern browsers (pretty much anything other IE <= 8), you can call Array's forEachmethod, passing it the list of elements (be it HTMLCollectionor NodeList) as the thisvalue:

在所有现代浏览器(几乎任何其他 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) {...});

If you're in the happy position of being able to use ES6 (i.e. you can safely ignore Internet Explorer or you're using an ES5 transpiler), you can use Array.from:

如果您很高兴能够使用 ES6(即您可以安全地忽略 Internet Explorer 或者您正在使用 ES5 转译器),您可以使用Array.from

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

回答by Athari

You can use Array.fromto convert collection to array, which is way cleaner than Array.prototype.forEach.call:

您可以使用Array.from将集合转换为数组,这比Array.prototype.forEach.call以下方式更清晰:

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

In older browsers which don't support Array.from, you need to use something like Babel.

在不支持的旧浏览器中Array.from,你需要使用像 Babel 这样的东西。



ES6 also adds this syntax:

ES6 还添加了以下语法:

[...document.getElementsByClassName("myclass")].forEach(
    (element, index, array) => {
        // do stuff
    }
);

Rest destructuring with ...works on all array-like objects, not only arrays themselves, then good old array syntax is used to construct an array from the values.

Rest 解构...适用于所有类似数组的对象,不仅仅是数组本身,然后使用良好的旧数组语法从值构造数组。



While the alternative function querySelectorAll(which kinda makes getElementsByClassNameobsolete) returns a collection which does have forEachnatively, other methods like mapor filterare missing, so this syntax is still useful:

虽然替代函数querySelectorAll(有点getElementsByClassName过时)返回一个集合,该集合本身确实具有forEach其他方法,例如mapfilter缺失,因此此语法仍然有用:

[...document.querySelectorAll(".myclass")].map(
    (element, index, array) => {
        // do stuff
    }
);

[...document.querySelectorAll(".myclass")].map(element => element.innerHTML);

回答by icl7126

Or you can use querySelectorAllwhich returns NodeList:

或者您可以使用querySelectorAllwhich 返回NodeList

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

Supported by modern browsers (including Edge, but not IE):
Can I use querySelectorAll
NodeList.prototype.forEach()

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

MDN:Document.querySelectorAll()

MDN:Document.querySelectorAll()

回答by james.garriss

Edit: Although the return type has changed in new versions of HTML (see Tim Down's updated answer), the code below still works.

编辑:尽管新版本的 HTML 中的返回类型发生了变化(请参阅 Tim Down 的更新答案),但下面的代码仍然有效。

As others have said, it's a NodeList. Here's a complete, working example you can try:

正如其他人所说,它是一个 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>

This works in IE 9, FF 5, Safari 5, and Chrome 12 on Win 7.

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

回答by Kloptikus

The result of getElementsByClassName()is not an Array, but an array-like object. Specifically it's called an HTMLCollection, not to be confused with NodeList(which has it's own forEach()method).

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

One simple way with ES2015 to convert an array-like object for use with Array.prototype.forEach()that hasn't been mentioned yet is to use the spread operator or spread syntax:

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

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

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

回答by Quentin

Is the result of getElementsByClassName an Array?

getElementsByClassName 的结果是一个数组吗?

No

If not, what is it?

如果不是,那是什么?

As with all DOM methods that return multiple elements, it is a NodeList, see https://developer.mozilla.org/en/DOM/document.getElementsByClassName

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

回答by Oriol

As already said, getElementsByClassNamereturns a HTMLCollection, which is defined as

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

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

Previously, some browsers returned a NodeListinstead.

以前,某些浏览器会返回一个NodeList

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

The difference is important, because DOM4 now defines NodeLists as iterable.

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

According to Web IDLdraft,

根据Web IDL草案,

Objects implementing an interface that is declared to be iterable support being iterated over to obtain a sequence of values.

Note: In the ECMAScript language binding, an interface that is iterable will have “entries”, “forEach”, “keys”, “values” and @@iteratorproperties on its interface prototype object.

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

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

That means that, if you want to use forEach, you can use a DOM method which returns a NodeList, like querySelectorAll.

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

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

Note this is not widely supported yet. Also see forEach method of Node.childNodes?

请注意,这尚未得到广泛支持。另请参阅Node.childNodes 的 forEach 方法?

回答by gildniy

This is the safer way:

这是更安全的方法:

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

回答by Haritsinh Gohil

getElementsByClassNamereturns HTMLCollectionin modern browsers.

getElementsByClassName在现代浏览器中返回HTMLCollection

which is array-like object similar to argumentswhich is iteratable by for...ofloop see below what MDNdoc is saying about it:

这是 类似数组的对象,类似于可通过for...of循环迭代的参数,请参见下面的MDN文档对此的描述:

The for...of statement creates a loop iterating over iterable objects, including: built-in String, Array, Array-like objects (e.g., argumentsor NodeList), TypedArray, Map, Set, and user-defined iterables. It invokes a custom iteration hook with statements to be executed for the value of each distinct property of the object.

对...的语句创建一个迭代循环迭代上的对象,包括:内置的字符串,数组,数组状物体(如参数或节点列表),TypedArray,地图,设置,和用户自定义iterables。它调用自定义迭代挂钩,其中包含要为对象的每个不同属性的值执行的语句。

example

例子

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

回答by StefanSL

Here is a test I created on jsperf: https://jsperf.com/vanillajs-loop-through-elements-of-class

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

The most perfomant version in Chrome and Firefox is the good old for loop in combination with document.getElementsByClassName:

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

In Safari this variant is the winner:

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

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

If you want the most perfomant variant for all browsers it might be this one:

如果您想要所有浏览器的最佳性能变体,它可能是这个:

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