ES6でノードリストをフィルタリングまたはマップする


90

ES6でノードリストをフィルタリングまたはマップする最も効率的な方法は何ですか?

私の読書に基づいて、私は次のオプションのいずれかを使用します:

[...nodelist].filter

または

Array.from(nodelist).filter

どちらをお勧めしますか?そして、たとえば配列を使用せずに、より良い方法はありますか?


2
基本的に、どちらの方法も同じことをします。を使用している場合はbabel、ではないものを[...coll]要求するだけです。Array.from(coll)Array
Leonid Beschastny 2015

FWIW、...構文はArray.from()通常の方法ですが、古いIDEではサポートされていない可能性があります。
Marat Tanalin 2015

回答:


131
  • [...nodelist] オブジェクトが反復可能である場合、オブジェクトから配列を作成します。
  • Array.from(nodelist)オブジェクトが反復可能である場合、またはオブジェクトが配列に似ている場合(has.lengthおよびnumeric props)、オブジェクトから配列を作成します

NodeList.prototype[Symbol.iterator]どちらの場合も反復可能であるため、2つの例が存在する場合は同じになります。NodeListただし、環境が反復可能なように構成されていない場合、最初の例は失敗し、2番目の例は成功します。Babel現在、このケースを適切に処理しいません

したがって、NodeList反復可能である場合、使用するのは本当にあなた次第です。私はおそらくケースバイケースで選ぶでしょう。利点の1つArray.fromは、マッピング関数の2番目の引数を取るのに対し、最初の引数は[...iterable].map(item => item)一時配列を作成するArray.from(iterable, item => item)必要があることです。ただし、リストをマッピングしていない場合は問題ありません。


17

TL; DR;

Array.prototype.slice.call(nodelist).filter

スライス()メソッドは配列を返します。返される配列は、コレクション(NodeListの)の浅いコピーがあること 、それはより速く動作しますのでArray.from() 、それは限り速く動作しますので)(Array.from

元のコレクションの要素は、次のように返された配列にコピーされます。

  • オブジェクト参照(実際のオブジェクトではない)の場合、sliceはオブジェクト参照を新しい配列にコピーします。元の配列と新しい配列の両方が同じオブジェクトを参照しています。参照されるオブジェクトが変更された場合、その変更は新しい配列と元の配列の両方に表示されます。
  • 文字列、数値、ブール値(String、Number、およびBooleanオブジェクトではない)の場合、sliceは値を新しい配列にコピーします。一方の配列の文字列、数値、またはブール値を変更しても、もう一方の配列には影響しません。

議論に関する簡単な説明

Array.prototype.slice(beginIndex、endIndex)

  • オプションの引数beginIndexおよびendIndexを取ります。それらが提供されていない場合、スライスはbeginIndex == 0を使用するため、コレクションからすべてのアイテムが抽出されます

Array.prototype.slice.call(namespace、beginIndex、endIndex)

  • 最初の引数としてオブジェクトを取ります。コレクションをオブジェクトとして使用する場合、文字通り、そのオブジェクトから直接スライスメソッドを呼び出すことを意味しますnamespace.slice()

2
このコードスニペットをありがとうございます。これは、限られた即時のヘルプを提供する可能性があります。適切な説明は、これが問題の良い解決策である理由を示すことによってその長期的な価値を大幅に改善し、他の同様の質問を持つ将来の読者にとってより役立つでしょう。あなたが行った仮定を含むいくつかの説明を追加するためにあなたの答えを編集してください。
Maximilian Peters

IEがサポートされているので、サポートされているのでArray.fromはないかと思います。IEマシンを見つける時が来ました。IE10とIE11でArray.fromを使用できたので、今は本当に混乱しています:\。このメソッドはIE10 + 11で機能しますが、すべてのドキュメントに別段の記載がある場合、Array.fromが機能するのは簡単ではありません。
CTS_AE 2018

Array.fromIE11の中に私のために動作しませんオブジェクト「から」プロパティまたはメソッドをサポートしていません
FuをRoのダー

おかげで、これはJavaScriptの古い実装で私のために働きました
VicSeedoubleyew19年

1
Array.fromまた、浅いコピーを返します。ですから、それがより速く動作するあなたがどのように結論付けるのかわかりませんArray#slice
ロバート

9

NodeListで直接使用する参照を見つけましたmap

Array.prototype.map.call(nodelist, fn)

私はそれをテストしていませんが、NodeListに直接アクセスする必要があるため、これがより高速であると考えられます。


4

これはどう:

// Be evil. Extend the prototype.
if (window.NodeList && !NodeList.prototype.filter) {
  NodeList.prototype.filter = Array.prototype.filter;
}

// Use it like you'd expect:
const noClasses = document
  .querySelectorAll('div')
  .filter(div => div.classList.length === 0)

これは、NodeList.forEachのMDNドキュメント(「Polyfill」の下)に記載されいるのと同じアプローチでありIE11、Edge、Chrome、およびFFで機能します。


わずかな警告ですが、nodeList.filterはノードリストの代わりに配列を提供します。^^問題になることはありませんが、簡単には忘れて
hanshenrik
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.