DOM オブジェクトの Javascript コレクション - Array.reverse() で元に戻せないのはなぜですか?
-
09-06-2019 - |
質問
次のコードのように DOM オブジェクトの配列を反転すると何が問題になる可能性がありますか。
var imagesArr = new Array();
imagesArr = document.getElementById("myDivHolderId").getElementsByTagName("img");
imagesArr.reverse();
Firefox 3 で、 reverse()
このメソッドを実行すると、スクリプトの実行が停止し、Web 開発者ツールバーのコンソールに次のエラーが表示されます。
imagesArr.reverse is not a function
の imagesArr
変数は、for ループと次のような要素を使用して反復処理できます。 imagesArr[i]
にアクセスできるのに、呼び出し時に配列として認識されないのはなぜですか? reverse()
方法?
解決
getElementsByTag 名は実際には NodeList 構造を返すためです。構文上の利便性のために、同様の配列のようなインデックス付けプロパティがありますが、 ない 配列。たとえば、エントリのセットは実際には常に動的に更新されます。myDivHolderId の下に新しい img タグを追加すると、そのタグは自動的に imageArr に表示されます。
見る http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-536297177 多くのための。
他のヒント
getElementsByTag()
配列の代わりに NodeList を返します。NodeList を Array に変換できますが、配列は別のオブジェクトになるため、逆にしても DOM ノードの位置には影響しないことに注意してください。
var listNodes = document.getElementById("myDivHolderId").getElementsByTagName("img");
var arrayNodes = Array.slice.call(listNodes, 0);
arrayNodes.reverse();
位置を変更するには、DOM ノードを削除し、すべてを正しい位置に再度追加する必要があります。
Array.prototype.slice.call(arrayLike, 0)
これは、配列のようなものを配列に変換する優れた方法ですが、JavaScript ライブラリを使用している場合は、実際にはさらに優れた/より高速な方法が提供される可能性があります。たとえば、jQuery には $.makeArray(arrayLike)
.
Array メソッドを NodeList で直接使用することもできます。
Array.prototype.reverse.call(listNodes);
getElementsByTag()
配列の代わりに NodeList を返します。NodeList を配列に変換してからそれを逆にする必要があります。
var imagesArr = [].slice.call(document.getElementById("myDivHolderId").getElementsByTagName("img"), 0).reverse();
この質問が古いことは知っていますが、W3C が定義を変更し、その結果これらのメソッドの戻り値が変更されたため、ここでの回答の一部が古くなっているため、少し説明する必要があると思います。 getElementsByTagName()
そして getElementsByClassName()
これらの方法 この回答を書いている時点では 空かどうかに関係なく、次のタイプのオブジェクトを返します。 HTMLCollection
そして ない NodeList
.
性質の違いみたいな children
型のオブジェクトを返します。 HTMLCollection
要素のみで構成されており、テキストやコメントのノードは含まれていないため、 childNodes
型のオブジェクトを返します。 NodeList
テキストやコメントなどの他のノード タイプも含めることができるためです。
注記:私はここで脱線して、その理由についての洞察力の欠如を表明したいと思います querySelectorAll()
メソッドは現在、 NodeList
ではありません HTMLCollection
なぜなら、それはドキュメント内の要素ノードに対してのみ機能し、他には何も機能しないからです。
おそらく、これは将来的に他のノードタイプがカバーされる可能性と関係があり、彼らはより将来性のあるソリューションを目指しましたが、本当のところは誰にも分かりません。:)
編集:を選択するというこの決定の背後にある論理的根拠が理解できたと思います。 NodeList
ではありません HTMLCollection
のために querySelectorAll()
.
彼らが建設して以来 HTMLCollection
排他的かつ完全にライブである必要があり、このメソッドにはライブ機能が必要ないため、 NodeList
その目的を経済的かつ効率的に最大限に果たすために、代わりに実装する必要があります。
最初の行は変数への代入を強制するものではないため無関係であり、JavaScript は逆に動作します。imageArr は Array() 型ではなく、getElementsByTagName("img") の戻り値の型です。この場合、Firefox 3 の HtmlCollection です。
このオブジェクトの唯一のメソッドは、インデクサーと長さです。逆に作業するには、逆方向に繰り返すだけです。