内のすべての要素の 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/in
nodeList または HTMLCollection を反復処理するために を使用しないでください。これを避ける理由を以下に説明します。
最新のブラウザ (Safari、Firefox、Chrome、Edge) の最新バージョンはすべて、またはなどの DOM リストの反復をサポートしていfor/of
ます。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 など) が取得されるだけでなく、プロパティlength
とitem
プロパティも取得されます。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
、1
、のみを取得します。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 およびNodeList
anと共に使用できるようになります。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.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
asでは機能しますdocument.querySelectorAll()
が、HTMLCollection
の as では機能しないdocument.getElementsByClassName()
ため、Edge で に使用するには反復子を手動で割り当てる必要がありますHTMLCollection
。1 つのコレクション タイプは修正されても、もう 1 つは修正されないのはなぜか、まったく謎です。ただし、少なくとも、現在のバージョンの Edge では、の結果をdocument.querySelectorAll()
ES6 構文で使用できるようになりました。for/of
また、上記の jsFiddle を更新して、両方HTMLCollection
をnodeList
個別にテストし、出力を jsFiddle 自体にキャプチャするようにしました。
2018年3月のES6の4回目のアップデート
mesqueeeb によると、Symbol.iterator
Safari にもサポートが組み込まれているため、または のfor (let item of list)
どちらにもを使用できます。document.getElementsByClassName()
document.querySelectorAll()
2018年4月のES6の5回目のアップデート
どうやら、反復処理のサポートはHTMLCollection
2018for/of
年秋に Edge 18 に導入される予定です。
2018年11月のES6の6回目のアップデート
Microsoft Edge v18 (2018 年秋の Windows Update に含まれています) では、Edge で for/of を使用して HTMLCollection と NodeList の両方を反復処理できることを確認できます。
そのため、現在ではすべての最新ブラウザに、for/of
HTMLCollection オブジェクトと NodeList オブジェクトの両方の反復処理に対するネイティブ サポートが含まれています。