Firefox 3.6でもdocument.querySelectorAll(...).map(...)
を実行できないだけでなく、まだ答えが見つからないというバグがあります。そのため、SOの質問にクロスポストすると思いましたこのブログ:
http://blowery.org/2008/08/29/yay-for-queryselectorall-boo-for-staticnodelist/
配列を取得しない技術的な理由を誰か知っていますか?または、なぜStaticNodeListがmap
、concat
などを使用できるように配列から継承しないのですか?
(ところで、必要な機能が1つだけの場合、NodeList.prototype.map = Array.prototype.map;
...のようなことができますが、この機能が(意図的に?)最初にブロックされているのはなぜですか?)
私はそれがW3Cの哲学的な決定であると信じています。 W3C DOM [spec]の設計はJavaScriptの設計と非常に直交しています。DOMはmeantプラットフォームおよび言語に中立であるためです。
「getElementsByFoo()
が順序付きNodeList
を返す」または「querySelectorAll()
がStaticNodeList
を返す」などの決定は非常に意図的であるため、実装は言語に基づいて返されたデータ構造を調整する必要がありません。依存する実装(_.map
_はJavaScriptおよびRubyの配列で利用可能ですが、C#のリストではnotのように)。
W3Cの狙いは低い:NodeList
には 読み取り専用_.length
_型unsigned long型のプロパティ を含めるべきだと言うでしょう。なぜなら、すべての実装が少なくともサポートできると信じているからですthatが、_[]
_インデックス演算子が位置要素の取得をサポートするためにオーバーロードされるべきであると明示的には言いません。彼らはgetElementsByFoo()
の実装を望む貧弱な小さな言語を失望させたくないからですただし、演算子のオーバーロードはサポートできません。これは、仕様の大部分に存在する一般的な哲学です。
John Resigには 同様のオプションの音声 があり、それに 彼が追加 :
私の議論は、
NodeIterator
があまりDOMに似ていないということではなく、JavaScriptにあまり似ていないということです。 JavaScript言語に存在する機能を利用せず、その能力を最大限に活用します...
私はやや共感します。 JavaScript機能を念頭に置いてDOMが具体的に記述されている場合、DOMを使用する方がはるかに扱いにくく、直感的です。同時に、W3Cの設計上の決定を理解しています。
ES2015(ES6)を使用できます スプレッド演算子 :
[...document.querySelectorAll('div')]
staticNodeListをアイテムの配列に変換します。
以下に使用方法の例を示します。
[...document.querySelectorAll('div')].map(x => console.log(x.innerHTML))
<div>Text 1</div>
<div>Text 2</div>
GetElementsByTagNameのように、DOMを更新すると結果が更新されるため、配列ではなくノードリストを返す理由がわかりません。とにかく、その結果を単純な配列に変換する非常に単純な方法は次のとおりです。
Array.prototype.slice.call(document.querySelectorAll(...));
そして、あなたは次のことができます:
Array.prototype.slice.call(document.querySelectorAll(...)).map(...);
クレセントが言ったことに加えて、
必要な関数が1つだけの場合は、NodeList.prototype.map = Array.prototype.mapのようにできます
これをしないでください!動作が保証されていません。
JavaScriptまたはDOM/BOM標準では、NodeList
コンストラクター関数がglobal/window
プロパティとしても存在すること、またはNodeList
によって返されるquerySelectorAll
が指定されていません。それから継承するか、そのプロトタイプが書き込み可能であるか、関数Array.prototype.map
は実際にNodeListで機能します。
NodeListは、「ホストオブジェクト」(およびIEおよび一部の古いブラウザー)であることが許可されています。Array
メソッドは、 JavaScriptの数値およびlength
プロパティを公開する「ネイティブオブジェクト」ですが、ホストオブジェクトで動作する必要はありません(IEでは動作しません)。
DOMリストのすべての配列メソッド(StaticNodeListだけでなく、すべて)を取得できないのは面倒ですが、信頼できる方法はありません。取得したすべてのDOMリストを手動で配列に変換する必要があります。
Array.fromList= function(list) {
var array= new Array(list.length);
for (var i= 0, n= list.length; i<n; i++)
array[i]= list[i];
return array;
};
Array.fromList(element.childNodes).forEach(function() {
...
});
あなたは単に次のことができると思います
Array.prototype.map.call(document.querySelectorAll(...), function(...){...});
私にぴったりです
これは、ここで他の人が提案した他の可能性の範囲に追加したいオプションです。知的楽しみのためだけのものであり、お勧めしません。
それのfunだけのために、querySelectorAll
をひざまずいてあなたに屈するように「強制」する方法があります:
Element.prototype.querySelectorAll = (function(QSA){
return function(){
return [...QSA.call(this, arguments[0])]
}
})(Element.prototype.querySelectorAll);
今度は、その機能を全面的に踏み越えて、誰がボスであるかを示すのは良い気分です。今、私はまったく新しいnamed関数ラッパーを作成し、すべてのコードにその奇妙な名前(ほとんどjQueryスタイル)または上記のように関数を1回オーバーライドして、残りのコードで元のDOMメソッド名querySelectorAll
を引き続き使用できるようにします。
あなたが正直に(あなたが知っている)を与えない限り、私はこれをいかなる方法でもお勧めしません。