HTMLCollection要素のforループ 質問する

HTMLCollection要素のforループ 質問する

内のすべての要素の ID を設定して取得しようとしていますHTMLCollectionOf。次のコードを記述しました:

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

しかし、コンソールには次の出力が表示されました。

event1
undefined

これは予想していたものとは違います。2 番目のコンソール出力は なのにundefined、1 番目のコンソール出力は なのはなぜですかevent1?

ベストアンサー1

元の質問に対する回答として、 の使い方がfor/in間違っています。コードでは、keyはインデックスです。したがって、疑似配列から値を取得するには を実行しlist[key]、 ID を取得するには を実行します。ただし、そもそもlist[key].idでこれを行うべきではありません。for/in

概要(2018年12月追加)

for/innodeList または HTMLCollection を反復処理するために を使用しないでください。これを避ける理由を以下に説明します。

最新のブラウザ (Safari、Firefox、Chrome、Edge) の最新バージョンはすべて、またはなどの DOM リストの反復をサポートしていfor/ofます。nodeListHTMLCollection

次に例を示します。

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++)これで、代わりにを使用する理由がわかったと思います。反復処理では01、のみを取得します。2


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 構造を a およびNodeListanと共に使用できるようになります。HTMLCollection

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 の現在のバージョンで動作します。これが動作する理由は、NodeList と HTMLCollection プロトタイプの両方に配列イテレータを添付し、for/of がそれらを反復処理するときに、配列イテレータを使用して反復処理するためです。

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


2016年12月のES6の2回目のアップデート

2016 年 12 月現在、Symbol.iteratorChrome 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 の のnodeListasでは機能しますdocument.querySelectorAll()が、HTMLCollectionの as では機能しないdocument.getElementsByClassName()ため、Edge で に使用するには反復子を手動で割り当てる必要がありますHTMLCollection。1 つのコレクション タイプは修正されても、もう 1 つは修正されないのはなぜか、まったく謎です。ただし、少なくとも、現在のバージョンの Edge では、の結果をdocument.querySelectorAll()ES6 構文で使用できるようになりました。for/of

また、上記の jsFiddle を更新して、両方HTMLCollectionnodeList個別にテストし、出力を jsFiddle 自体にキャプチャするようにしました。

2018年3月のES6の4回目のアップデート

mesqueeeb によると、Symbol.iteratorSafari にもサポートが組み込まれているため、または のfor (let item of list)どちらにもを使用できます。document.getElementsByClassName()document.querySelectorAll()

2018年4月のES6の5回目のアップデート

どうやら、反復処理のサポートはHTMLCollection2018for/of年秋に Edge 18 に導入される予定です。

2018年11月のES6の6回目のアップデート

Microsoft Edge v18 (2018 年秋の Windows Update に含まれています) では、Edge で for/of を使用して HTMLCollection と NodeList の両方を反復処理できることを確認できます。

そのため、現在ではすべての最新ブラウザに、for/ofHTMLCollection オブジェクトと NodeList オブジェクトの両方の反復処理に対するネイティブ サポートが含まれています。

おすすめ記事