2012-12-19 2 views
18

プレーンJavaScriptで素敵な何かがdocument.querySelectorAllによって返された項目に、forEachmapfilter、などを使用できるようになり、document.getElementsBy*などquerySelectorAllによって返された擬似配列に対してforEachを使用するにはどうすればよいですか?

This'dはjQueryのにはあまり依存し、単にクリーンなコードにつながります。今、これは醜いやり方で私たちがやり遂げる方法です:

[].forEach.call(document.querySelectorAll(sel), function(el) { 
}); 

これは冗長です。

forEachなどの要素をすぐに返すことができる方法はありますか?

+1

なぜ誰もが( '[]')代わりに 'Array.prototype.forEach'を使用しての配列を割り当てるのですか? –

答えて

14

素朴な方法は、あなたがChromeでテストした場合は、これを行うには、次のようになります。

NodeList.prototype.forEach = Array.prototype.forEach; 

これは動作します。 WebkitについてFirefoxではそうはしません。 FFはHTMLCollection ...

私が見つけた最もクロスブラウザの道を返すので:

NodeList.prototype.forEach = HTMLCollection.prototype.forEach = Array.prototype.forEach; 

それはIE8で動作すると、オブジェクトをホストするプロパティを追加するとき、彼らはチョークので、しかし低下しませんプロトタイプ。

全リスト:

NodeList.prototype.forEach = HTMLCollection.prototype.forEach = Array.prototype.forEach; 
NodeList.prototype.map = HTMLCollection.prototype.map = Array.prototype.map; 
NodeList.prototype.filter = HTMLCollection.prototype.filter = Array.prototype.filter; 
NodeList.prototype.reduce = HTMLCollection.prototype.reduce = Array.prototype.reduce; 
NodeList.prototype.reduceRight = HTMLCollection.prototype.reduceRight = Array.prototype.reduceRight; 
NodeList.prototype.every = HTMLCollection.prototype.every = Array.prototype.every; 
NodeList.prototype.some = HTMLCollection.prototype.some = Array.prototype.some; 

それとも、私たちの愛するBergiを喜ばせるために(そしてそれクリーナーですので、また):

['forEach', 'map', 'filter', 'reduce', 'reduceRight', 'every', 'some'].forEach(
    function(p) { 
    NodeList.prototype[p] = HTMLCollection.prototype[p] = Array.prototype[p]; 
}); 

がperfectionkillsへのリンクを考えると、それはそこにほとんど無関係です。問題は、DOMが拡張されたときにブラウザでほとんど同じように動作していないことです。この変更はIE < = 8を除くすべてのブラウザで正常です。

+4

http://perfectionkills.com/whats-wrong-with-extending-the-dom/へのリンクがありません。また、あなたの "完全なリスト"のためにループを使用してください – Bergi

+0

@Bergi編集: –

+0

私はDOMを拡張したくありません。 – andlrc

6
function forEach(a, fn) { 
    return [].forEach.call(a, fn); 
}; 

forEach(document.querySelectorAll(sel), function(el) { 
}); 

そして、もっと多く:

function map(a, fn) { 
    return [].map.call(a, fn); 
}; 
function filter(a, fn) { 
    return [].filter.call(a, fn); 
}; 
function reduce(a, fn) { 
    return [].reduce.call(a, fn); 
}; 
function reduceRight(a, fn) { 
    return [].reduceRight.call(a, fn); 
}; 
function every(a, fn) { 
    return [].every.call(a, fn); 
}; 
function some(a, fn) { 
    return [].some.call(a, fn); 
}; 

たぶんあなたには、いくつかの状況で

[].slice.call(a) 

が必要になります。

function forEach(a, fn) { 
    return [].forEach.call([].slice.call(a), fn); 
} 
+0

ええ、ええ、それを言い忘れました。私はむしろ(私はそれを行う方法を私の頭から覚えていない)バインドメソッドを使用したいと思います。しかし、私はまだ私の答えで示された方法を好む。それはもっと "dommy"と感じます。 –

+0

@FlorianMargaine私は誰かが処刑されていると思う? – andlrc

+1

Nope。正直言って、質問/答えは帽子狩りでした。私は正直に私の答えに示された方法を好む。私の前のコメントで言われたように、私はあなたの方法について既に知っていました - 私はそれを特に好きではありません。それに、なぜ私がすでにリペアされているときに売春をするのか? –

2

あなたはプロトタイプを変更したいとして、すべてのアレイの機能はそれだけのアレイにあなたのコレクションを変換する方が簡単な場合があり、仕事だけしたくない場合は、次の

Array.from(document.querySelectorAll('a')) 

すべての配列の機能が利用できるようになりますJavaScriptの新バージョンがリリースされたときにコードを更新する必要はありません:

Array.from(document.querySelectorAll('a')).forEach(a => console.log(a))