1. ホーム
  2. javascript

[解決済み] HTMLCollectionの要素に対してのループ

2022-03-01 12:01:39

質問

の全要素のidを取得するように設定しようとしています。 HTMLCollectionOf . 以下のようなコードを書きました。

var list = document.getElementsByClassName("events");
console.log(list[0].id);
for (key in list) {
    console.log(key.id);
}

しかし、コンソールに次のような出力が出ました。

event1
undefined

というのは、私が期待したものではありません。なぜ2番目のコンソール出力は undefined が、最初のコンソール出力は event1 ?

解決方法は?

元の質問に対して、あなたが使っているのは for/in が正しくありません。 あなたのコードでは key はインデックスです。 つまり、擬似配列から値を取得するためには list[key] で、idを取得するためには list[key].id . しかし、このようなことをするのは for/in をそもそも

概要(2018年12月追記)

は絶対に使用しないでください。 for/in を使用して、nodeList または HTMLCollection を反復処理します。 これを避ける理由は、以下に記述されています。

最近のブラウザ(Safari、Firefox、Chrome、Edge)は、すべて for/of のような DOM リストに対する反復処理です。 nodeList または HTMLCollection .

以下はその例です。

var list = document.getElementsByClassName("events");
for (let item of list) {
    console.log(item.id);
}

古いブラウザ(IEのようなものを含む)を含めるために、これはどこでも動作するようになります。

var list = document.getElementsByClassName("events");
for (var i = 0; i < list.length; i++) {
    console.log(list[i].id); //second console output
}


使用すべきでない理由の説明 for/in

for/in は、オブジェクトのプロパティを繰り返し処理するためのものです。 つまり、オブジェクトの反復可能なすべてのプロパティを返します。 一見、配列に対して動作しているように見えますが(配列要素や擬似配列要素を返す)、配列のような要素から期待するものとは異なる、オブジェクトの他のプロパティを返すこともあります。 そして、なんといっても HTMLCollection または nodeList オブジェクトは、どちらも他のプロパティを持つことができ、それらは for/in の繰り返しです。 Chromeで試してみたところ、あなたが行った方法で反復処理を行うと、リスト内のアイテム(インデックス0、1、2など)が取得されますが、同時に lengthitem プロパティを使用します。 また for/in の繰り返しは、HTMLCollectionでは単に機能しません。


参照 http://jsfiddle.net/jfriend00/FzZ2H/ でHTMLCollectionを反復できない理由については、こちらをご覧ください。 for/in .

Firefoxでは for/in の反復は、これらの項目 (オブジェクトの反復可能なすべてのプロパティ) を返すでしょう。

0
1
2
item
namedItem
@@iterator
length

を使用する理由がおわかりいただけたでしょうか? for (var i = 0; i < list.length; i++) を取得する代わりに 0 , 12 をイテレーションで使用します。


NodeListとHTMLCollectionのイテレーションに対するブラウザサポートの変遷

以下は、2015年から2018年の間にブラウザがどのように進化してきたかを示すもので、反復するための追加の方法を提供しています。 上記で説明したオプションを使用できるため、モダンブラウザではいずれも現在必要ありません。

2015年のES6へのアップデート

ES6に追加されたのは Array.from() これは、配列のような構造を実際の配列に変換するものです。 これにより、このように直接リストを列挙することができます。

"use strict";

Array.from(document.getElementsByClassName("events")).forEach(function(item) {
   console.log(item.id);
});

動作デモ(2016年4月現在、Firefox、Chrome、Edgeにて)。 https://jsfiddle.net/jfriend00/8ar4xn2s/


2016年のES6に向けたアップデート

ES6 の for/of 構文が使えるようになりました。 NodeListHTMLCollection を追加するだけです。

NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
HTMLCollection.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];

すると、できるようになります。

var list = document.getElementsByClassName("events");
for (var item of list) {
    console.log(item.id);
}

これは、現在のバージョンのChrome、Firefox、Edgeで動作しています。 これは、ArrayイテレータをNodeListとHTMLCollectionの両方のプロトタイプにアタッチし、for/ofがそれらを反復するとき、Arrayイテレータを使用して反復するようにしたため、動作しています。

動作デモです。 http://jsfiddle.net/jfriend00/joy06u4e/ .


2016年12月のES6向けアップデート第2弾

2016年12月現在 Symbol.iterator のサポートは、Chrome v54とFirefox v50にビルトインされたので、以下のコードはそれだけで動作します。 Edgeにはまだビルトインされていません。

var list = document.getElementsByClassName("events");
for (let item of list) {
    console.log(item.id);
}

動作デモ(ChromeとFirefoxで)。 http://jsfiddle.net/jfriend00/3ddpz8sp/

2017年12月のES6向けアップデート第3弾

2017年12月現在、このケイパビリティはEdge 41.16299.15.0で動作します。 nodeList のように document.querySelectorAll() とは異なり HTMLCollection のように document.getElementsByClassName() で使用するには、手動でイテレータを割り当てる必要があります。 HTMLCollection . なぜ、一方のコレクションタイプを修正し、もう一方のコレクションタイプを修正しないのか、まったく謎です。 でも、少なくとも document.querySelectorAll() をES6で使用する場合 for/of の文法は、現在のEdgeのバージョンで使用されています。

また、上記のjsFiddleを更新し、両方のテストができるようにしました。 HTMLCollectionnodeList を個別に作成し、その出力をjsFiddle自体に取り込みます。

2018年3月のES6向けアップデート第4弾

メスキューブあたり。 Symbol.iterator のサポートがSafariにも組み込まれました。 for (let item of list) のどちらかに対して document.getElementsByClassName() または document.querySelectorAll() .

2018年4月のES6向けアップデート第5弾

を反復することをサポートしたようです。 HTMLCollectionfor/of が、2018年秋にEdge 18に登場します。

2018年11月のES6向け第6弾アップデート

Microsoft Edge v18(2018年秋のWindows Updateに含まれるもの)では、EdgeでHTMLCollectionとNodeListの両方をfor/ofで反復できるようになったことが確認できます。

つまり、現在ではすべてのモダンブラウザで for/of HTMLCollection と NodeList オブジェクトの両方の反復処理。