[解決済み] HTMLCollectionの要素に対してのループ
質問
の全要素の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など)が取得されますが、同時に
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 構文が使えるようになりました。
NodeList
と
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で動作しています。 これは、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を更新し、両方のテストができるようにしました。
HTMLCollection
と
nodeList
を個別に作成し、その出力をjsFiddle自体に取り込みます。
2018年3月のES6向けアップデート第4弾
メスキューブあたり。
Symbol.iterator
のサポートがSafariにも組み込まれました。
for (let item of list)
のどちらかに対して
document.getElementsByClassName()
または
document.querySelectorAll()
.
2018年4月のES6向けアップデート第5弾
を反復することをサポートしたようです。
HTMLCollection
で
for/of
が、2018年秋にEdge 18に登場します。
2018年11月のES6向け第6弾アップデート
Microsoft Edge v18(2018年秋のWindows Updateに含まれるもの)では、EdgeでHTMLCollectionとNodeListの両方をfor/ofで反復できるようになったことが確認できます。
つまり、現在ではすべてのモダンブラウザで
for/of
HTMLCollection と NodeList オブジェクトの両方の反復処理。
関連
-
[解決済み】Javascriptのコールバック関数がFirefoxで「Callback is not a function」というエラーを投げる
-
[解決済み】ある要素を別の要素に移動させるには?
-
[解決済み] [Solved] Uncaught Invariant Violation: 前のレンダリング中よりも多くのフックをレンダリングする
-
[解決済み] jQueryでチェックボックスに "checked "を設定する
-
[解決済み] JavaScriptのオブジェクトが空であることをテストするにはどうすればよいですか?
-
[解決済み] JavaScriptのオブジェクトをループスルーまたは列挙するにはどうすればよいですか?
-
[解決済み] 私のJavaScriptコードは "No 'Access-Control-Allow-Origin' header is present on requested resource "というエラーを受け取りますが、Postmanはそうならないのはなぜですか?
-
[解決済み] Node.jsを完全にアンインストールして、最初から再インストールする方法 (Mac OS X)
-
[解決済み] どのDOM要素にフォーカスがあるかを調べるには?
-
[解決済み] Node.jsでディレクトリに存在するすべてのファイル名のリストを取得する方法は?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】パッシブイベントリスナー内部でpreventDefaultができない
-
[解決済み】JavaScriptのボタンonclickが機能しない
-
[解決済み】JavaScript ランタイムエラー:'$'が未定義です。
-
[解決済み】エラー:リスン EACCES 0.0.0.0:80 OSx Node.js
-
[解決済み】エラー:リクエストのエンティティが大きすぎる
-
[解決済み】npm install --legacy-peer-deps は具体的に何をするのですか?どんなときに推奨されるのか/どんな使用例が考えられるのか?
-
[解決済み】Vueのテンプレートまたはレンダー関数が定義されていない 私はどちらも使っていないのですが?
-
[解決済み】 Uncaught Reference Error: stLight is not defined (in Chrome only)
-
[解決済み】Syntax error: JavaScriptの不正なreturnステートメント
-
[解決済み】未定義のプロパティ 'forEach' を読み取ることができない