Ho imparato dai libri che dovresti scrivere per un ciclo come questo:
for(var i=0, len=arr.length; i < len; i++){ // blah blah }
quindi l’ arr.length
non verrà calcolato ogni volta.
Altri dicono che il compilatore farà qualche ottimizzazione, quindi puoi semplicemente scrivere:
for(var i=0; i < arr.length; i++){ // blah blah }
Voglio solo sapere qual è il modo migliore in pratica?
Dopo aver eseguito questo test con i browser più moderni …
Attualmente , la forma più veloce di loop (e secondo me la più sintatticamente ovvia).
uno standard per il loop con memorizzazione nella cache di lunghezza
for (var i = 0, len = myArray.length; i < len; i++) { }
Direi che questo è sicuramente un caso in cui apprezzo gli sviluppatori di motori JavaScript. Un tempo di esecuzione dovrebbe essere ottimizzato per chiarezza , non intelligenza .
Il modo più veloce per effettuare il loop di un array javascript è:
var len = arr.length; while (len--) { // blah blah }
Vedi http://blogs.oracle.com/greimer/entry/best_way_to_code_a per un confronto completo
A partire da giugno 2016 , facendo alcuni test nell’ultimo Chrome (71% del mercato dei browser a maggio 2016 e in aumento):
Credo che questo thread sia troppo vecchio e che i programmatori ingannevoli pensino di aver bisogno di memorizzare la lunghezza, o usare reverse reverse con decrementi per ottenere prestazioni migliori, scrivendo un codice che sia meno leggibile e più incline agli errori di un semplice ciclo semplice. Pertanto, consiglio:
Se la tua app esegue iterazioni su molti articoli o il tuo codice loop è all’interno di una funzione che viene usata spesso, un ciclo for semplice è la risposta:
for (var i = 0; i < arr.length; i++) { // Do stuff with arr[i] or i }
Se la tua app non esegue realmente iterazioni con molti articoli o hai solo bisogno di eseguire piccole iterazioni qua e là, l'uso dello standard forEach callback o qualsiasi funzione simile dalla tua libreria JS di scelta potrebbe essere più comprensibile e meno sobject a errori, dal momento che l'ambito della variabile dell'indice è chiuso e non è necessario utilizzare parentesi, accedendo direttamente al valore dell'array:
arr.forEach(function(value, index) { // Do stuff with value or index });
Se hai davvero bisogno di grattare alcuni millisecondi mentre iterating su miliardi di righe e la lunghezza dell'array non cambia attraverso il processo, potresti prendere in considerazione la memorizzazione nella cache della lunghezza nel ciclo for. Anche se penso che questo non sia davvero necessario al giorno d'oggi:
for (var i = 0, len = arr.length; i < len; i++) { // Do stuff with arr[i] }
Se l’ordine non è importante, preferisco questo stile:
for(var i = array.length; i--; )
Mette in cache la lunghezza ed è molto più breve da scrivere. Ma itererà sopra la matrice in ordine inverso.
2014 While
è tornato
Pensa solo logico.
Guarda questo
for( var index = 0 , length = array.length ; index < length ; index++ ) { //do stuff }
for
ha 3 parametri Ora dimmi perché questo dovrebbe essere più veloce di:
var length = array.length; while( --length ) { //or length-- //do stuff }
while
ha solo un parametro Ero completamente confuso quando Chrome 28 ha dimostrato che il ciclo for è più veloce del tempo. Questo deve avere una specie di
"Uh, tutti usano il ciclo for, concentriamoci su questo quando sviluppiamo per chrome".
Ma ora, nel 2014, il ciclo while è tornato su chrome. è 2 volte più veloce, su altri browser più vecchi è sempre stato più veloce.
Ultimamente ho fatto alcuni nuovi test. Ora nel mondo reale, i codici brevi non valgono nulla e jsperf non può effettivamente eseguire correttamente il ciclo while, perché ha bisogno di ricreare l'array. La lunghezza richiede anche tempo.
NON è ansible ottenere la velocità effettiva di un ciclo while su jsperf.
è necessario creare la propria funzione personalizzata e verificarla con window.performance.now()
E sì ... non c'è modo che il ciclo while sia semplicemente più veloce.
Il vero problema è in realtà la manipolazione dom / rendering tempo / tempo di disegno o comunque vuoi chiamarlo.
Ad esempio, ho una scena su canvas in cui ho bisogno di calcolare le coordinate e le collisioni ... ciò avviene tra 10-200 MicroSeconds (non millisecondi). in realtà ci vogliono diversi millisecondi per renderizzare tutto. Lo stesso come in DOM.
MA
C'è un altro modo super performante che usa il loop
for in alcuni casi ... per esempio per copiare / clonare un array
for( var i = array.length ; i > 0 ; arrayCopy[ --i ] = array[ i ] // doing stuff );
Si noti la configurazione dei parametri:
Detto questo, questo conferma che macchine come il -
scrivendo che stavo pensando di renderlo un po 'più breve e rimuovere alcune cose inutili e ho scritto questo usando lo stesso stile:
for( var i = array.length ; i-- ; arrayCopy[ i ] = array[ i ] // doing stuff );
Anche se è più corto, sembra che usarlo ancora una volta rallenti tutto. È 1/5 più lento del ciclo precedente e il primo.
Nota: il ;
è molto importante dopo il looo senza {}
Anche se ti ho appena detto che jsperf non è il modo migliore per testare gli script ... ho aggiunto questo 2 loop qui
http://jsperf.com/caching-array-length/40
Ed ecco un'altra risposta sulle prestazioni in javascript
https://stackoverflow.com/a/21353032/2450730
Questa risposta è per mostrare modi performanti di scrivere javascript. Quindi se non riesci a leggerlo, chiedi e otterrai una risposta o leggi un libro su javascript http://www.ecma-international.org/ecma-262/5.1/
http://jsperf.com/caching-array-length/60
L’ultima revisione del test, che ho preparato (riutilizzando quella più vecchia), mostra una cosa.
La lunghezza del caching non è molto importante, ma non danneggia.
Ogni prima esecuzione del test di cui sopra (nella scheda appena aperta) offre i migliori risultati per gli ultimi 4 snippet (3 °, 5 °, 7 ° e 10 ° in classifica) in Chrome, Opera e Firefox nel mio Debian Squeeze 64-bit (il mio hardware desktop ). Le corse successive danno risultati abbastanza diversi.
Le conclusioni sul rendimento sono semplici:
!==
invece di <
. shift()
-ing è efficiente. tl; dr
Oggi (2011.10) sotto il modello sembra essere il più veloce.
for (var i = 0, len = arr.length; i !== len; i++) { ... }
arr.length
che la cache di arr.length
non è cruciale qui, quindi puoi semplicemente provare per i !== arr.length
e le prestazioni non scenderanno, ma otterrai un codice più breve.
PS: So che in snippet con shift()
suo risultato potrebbe essere usato invece di accedere allo 0 ° elemento, ma in qualche modo trascurato che dopo aver riutilizzato la revisione precedente (che aveva sbagliato durante i loop), e dopo non volevo perdere già ottenuto risultati.
“Migliore” come nella pura performance? o prestazioni e leggibilità?
La “migliore” prestazione pura è questa, che utilizza una cache e l’operatore di prefisso ++ (i miei dati: http://jsperf.com/caching-array-length/189 )
for (var i = 0, len = myArray.length; i < len; ++i) { // blah blah }
Direi che il ciclo for senza cache è il miglior bilanciamento tra tempo di esecuzione e tempo di lettura del programmatore. Ogni programmatore che ha iniziato con C / C ++ / Java non sprecherà un ms a dover leggere questo
for(var i=0; i < arr.length; i++){ // blah blah }
È solo il 2018 quindi un aggiornamento potrebbe essere bello …
E devo davvero essere in disaccordo con la risposta accettata . ecco un punto di riferimento su tutti i metodi http://jsben.ch/mW36e
arr.forEach( a => { // ... }
e sice puoi vedere un sacco di for-loop like for(a = 0; ... )
quindi vale la pena menzionare che senza le variabili ‘var’ verranno definite globalmente e questo può influenzare notevolmente la velocità in modo che diventi lento.
var arr = new Array(11111111).fill().map((_,n)=>n); var benches = [ [ "empty", () => { for(var a = 0, l = arr.length; a < l; ++a); }] , ["for-loop", () => { for(var a = 0, l = arr.length; a < l; ++a) var b = arr[a] + 1; }] , ["for-loop++", () => { for(var a = 0, l = arr.length; a < l; a++) var b = arr[a] + 1; }] , ["for-loop - arr.length", () => { for(var a = 0; a < arr.length; ++a ) var b = arr[a] + 1; }] , ["reverse for-loop", () => { for(var a = arr.length - 1; a >= 0; --a ) var b = arr[a] + 1; }] ,["while-loop", () => { var a = 0, l = arr.length; while( a < l ) { var b = arr[a] + 1; ++a; } }] , ["reverse-do-while-loop", () => { var a = arr.length - 1; // CAREFUL do { var b = arr[a] + 1; } while(a--); }] , ["forEach", () => { arr.forEach( a => { var b = a + 1; }); }]]; function bench(title, f) { var t0 = performance.now(); var res = f(); return performance.now() - t0; // console.log( `${title} took ${t1-t0} millisec` ); } var globalVarTime = bench( "for-loop without 'var'", () => { // Here if you forget to put 'var' so variables'll be global for(a = 0, l = arr.length; a < l; ++a) var b = arr[a] + 1; }); var times = benches.map( a => [a[0], bench(...a)] ) .sort( (a,b) => a[1]-b[1] ); var max = times[times.length-1][1]; times = times.map( a => {a[2] = (a[1]/max)*100; return a; } ); var template = (title, time, n) => { return `` + `${title} ` + ` ${Number(time.toFixed(3))}msec` + ``; } var strRes = times.map( t => template(...t) ).join("\n") + `
for-loop without 'var' ${globalVarTime} msec.`; var $container = document.getElementById("container"); $container.innerHTML = strRes;
body { color:#fff; background:#333; font-family:helvetica; } body > div > div { clear:both } body > div > div > span { float:left; width:43%; margin:3px 0; text-align:right; } body > div > div > span:nth-child(2) { text-align:left; background:darkorange; }
** Memorizza la lunghezza dell’array all’interno del ciclo, alcuni secondi di tempo saranno elusi. Dipende dagli elementi dell’array se ci sono più elementi nell’array c’è una grande differenza rispetto a Ms of time *
**
sArr; //Array[158]; for(var i = 0 ; i
**
**
sArr; //Array[158]; for(var i = 0,len = sArr.length ; i < len ; i++) { callArray(sArr[i]); //function call } ***end: 1.354ms***
**
Questo sembra essere il modo più veloce di gran lunga …
var el; while (el = arr.shift()) { el *= 2; }
Prendi in considerazione che questo consumerà la matrice, mangiandola e lasciando nulla lasciato …
Scrivo sempre nel primo stile.
Anche se un compilatore è abbastanza intelligente da ottimizzarlo per gli array, ma è comunque intelligente se stiamo usando DOMNodeList qui o qualche object complicato con lunghezza calcasting?
So qual è la domanda sugli array, ma penso che sia una buona pratica scrivere tutti i loop in un unico stile.
È l’anno 2017 .
Ho fatto alcuni test.
https://jsperf.com/fastest-way-to-iterate-through-an-array/
Sembra che il metodo while
sia il più veloce su Chrome.
Sembra che il decremento a sinistra ( --i
) sia molto più veloce degli altri ( ++i
, i--
, i++
) su Firefox.
Questo approccio è il digiuno in media. Ma itera l’array in ordine inverso.
let i = array.length; while (--i >= 0) { doSomething(array[i]); }
Se l’ordine di inoltro è importante, utilizzare questo approccio.
let ii = array.length; let i = 0; while (i < ii) { doSomething(array[i]); ++i; }
var arr = []; // The array var i = 0; while (i < arr.length) { // Do something with arr[i] i++; }
i ++ è più veloce di ++ i, --i e io--
Inoltre, è ansible salvare l'ultima riga facendo arr [i ++] l'ultima volta che è necessario accedere a i (ma questo può essere difficile da eseguire il debug).
Puoi testarlo qui (con altri test del ciclo): http://jsperf.com/for-vs-whilepop/5
La soluzione più elegante che conosco è usare la mappa.
var arr = [1,2,3]; arr.map(function(input){console.log(input);});
Ho provato alcuni altri modi per iterare un enorme array e ho scoperto che dimezzare la lunghezza dell’array e poi iterare entrambe le metà in un singolo ciclo è più veloce. Questa differenza di prestazioni può essere vista durante l’elaborazione di enormi matrici .
var firstHalfLen =0; var secondHalfLen = 0; var count2=0; var searchterm = "face"; var halfLen = arrayLength/2; if(arrayLength%2==halfLen) { firstHalfLen = Math.ceil(halfLen); secondHalfLen=Math.floor(halfLen); } else { firstHalfLen=halfLen; secondHalfLen=halfLen; } for(var firstHalfCOunter=0,secondHalfCounter = arrayLength-secondHalfLen; firstHalfCOunter < firstHalfLen; firstHalfCOunter++) { if(mainArray[firstHalfCOunter].search(new RegExp(searchterm, "i"))> -1) { count2+=1; } if(secondHalfCounter < arrayLength) { if(mainArray[secondHalfCounter].search(new RegExp(searchterm, "i"))> -1) { count2+=1; } secondHalfCounter++; } }
Alcuni confronti delle prestazioni (usando timer.js) tra la lunghezza della cache per il ciclo VS il metodo di cui sopra.
Un altro test di jsperf.com: http://jsperf.com/while-reverse-vs-for-cached-length
Il ciclo inverso mentre sembra essere il più veloce. L’unico problema è che mentre (–i) si fermerà a 0. Come posso accedere all’array [0] nel mio ciclo allora?
A partire da settembre 2017 questi test di jsperf mostrano il seguente schema per essere i più performanti su Chrome 60:
function foo(x) { x; }; arr.forEach(foo);
Qualcuno è in grado di riprodurre?
Un ciclo while di base è spesso il più veloce. jsperf.com è una fantastica sandbox per testare questi tipi di concetti.
Mentre il ciclo è un po ‘più veloce del ciclo.
var len = arr.length; while (len--) { // blah blah }
Usa invece il ciclo while
Prova questo:
var myarray =[], i = myarray.lenght; while(i--){ // do somthing }