2012-12-19 9 views
18

Qualcosa di bello con la pianura javascript sarebbe quello di essere in grado di utilizzare forEach, map, filter, ecc, sulle voci restituite da document.querySelectorAll, document.getElementsBy* eccCome avere forOach disponibile su pseudo-array restituiti da querySelectorAll?

This'd portano a meno dipendenza jQuery, e il codice semplicemente più pulito . In questo momento, è così che possiamo farlo, in un modo brutto:

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

Questo è ... verboso.

Un modo per essere in grado di utilizzare immediatamente forEach sugli elementi restituiti?

+1

Perché tutti allocare un array ('[]') invece di utilizzare 'Array.prototype.forEach'? –

risposta

14

Un modo semplice sarebbe quello di fare questo se testato su Chrome:

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

Questo funziona. Su Webkit. Tuttavia non funziona su Firefox. Perché FF restituisce un HTMLCollection ...

Il modo più cross-browser che ho trovato:

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

Non funziona su IE8 e abbassare però, perché soffocare quando si aggiungono le proprietà per ospitare gli oggetti prototipi.

Lista completa:

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; 

Oppure, per soddisfare i nostri cari Bergi (e anche perché è più pulito):

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

Considerando il link al perfectionkills, è per lo più irrilevante lì. Il problema è che il DOM non si comporta per lo più sui browser quando è esteso. Questa modifica è normale in tutti i browser eccetto IE < = 8.

+4

Mi manca il link a http://perfectionkills.com/whats-wrong-with-extending-the-dom/. Inoltre, si prega di utilizzare un ciclo per la "lista completa" – Bergi

+0

@ Bergi Modificato :) –

+0

Non mi piace estendere il dom. – andlrc

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

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

E molti di più:

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); 
}; 

Forse avrete bisogno

[].slice.call(a) 

in alcune situazioni.

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

Uh, sì, ho dimenticato di dirlo. Preferirei usare comunque il metodo 'bind' (non ricordo di aver capito come farlo). Ma continuo a preferire il modo mostrato nella mia risposta. Sembra più "dommy". –

+0

@ FlorianMargaine Penso che qualcuno stia ripetendo il puttane ?? – andlrc

+1

No. Per essere onesti, la domanda/risposta era per la caccia al cappello. Preferisco sinceramente il modo mostrato nella mia risposta. Come ho detto nel mio precedente commento, sapevo già a proposito di te - semplicemente non mi piace particolarmente. Inoltre, perché ripare il mormorio quando sono già stato ricoperto ?! –

2

Se non ti piace cambiare i prototipi e desidera che tutte le funzioni per gli array a solo di lavoro, può essere più facile da convertire solo la vostra collezione ad un array:

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

Tutte le funzioni di array saranno disponibili , nessuna necessità di aggiornare il codice quando viene rilasciato la nuova versione di JavaScript:

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