Qual è il modo più veloce per passare in rassegna un array in JavaScript?


248

Ho imparato dai libri che dovresti scrivere per loop in questo modo :

for(var i=0, len=arr.length; i < len; i++){
    // blah blah
}

quindi arr.lengthnon verrà calcolato ogni volta.

Altri dicono che il compilatore farà un po 'di ottimizzazione per questo, quindi puoi semplicemente scrivere:

for(var i=0; i < arr.length; i++){
    // blah blah
}

Voglio solo sapere qual è il modo migliore in pratica?


1
vale anche la pena dare un'occhiata quando si ha a che fare con il loop array: jsperf.com/array-loop-var-caching
cloakedninjas

@ wong2 Questo benchmark di Browserdiet ha una raccolta più completa di alternative.
Domi,


Migliorato sul precedente jsben: jsben.ch/#/R6LbS
Corbfon

Possiamo presentare il for ... ofloop a questa competizione? La sintassi sembra ancora più semplice di un ciclo for senza memorizzazione nella cache e voglio sapere se dovrei passare a usare for of loop.
programmatore

Risposte:


339

Dopo aver eseguito questo test con i browser più moderni ...

http://jsben.ch/dyM52

Attualmente , la forma più veloce di loop (e secondo me la più sintatticamente ovvia).

uno standard per loop con memorizzazione nella cache della lunghezza

for (var i = 0, len = myArray.length; i < len; i++) {

}

Direi che questo è sicuramente un caso in cui applaudo gli sviluppatori del motore JavaScript. Un tempo di esecuzione dovrebbe essere ottimizzato per chiarezza , non per intelligenza .


6
È interessante notare che in IE9 questo è più veloce: for (var i = 0, len = myArray.length; i <len; ++ i) {} // prefix incr, anziché postfix
Christopher Bennage,


4
Ho provato usando l'operatore prefisso come suggerito da @BennettMcElwee e funziona un po 'più velocemente: for(var i=0, len=myArray.length; i<len; ++i) controlla jsperf.com/caching-array-length/84
victmo

21
Devi stare attento usando questo ciclo. Ho iniziato a usarlo e ho avuto un bug difficile da rintracciare a causa di un errore che ho fatto. Se annidate due loop in questo modo: jsfiddle.net/KQwmL/1 . Devi fare attenzione a nominare la var in modo diverso nei due loop, altrimenti il ​​secondo loop sovrascriverà la prima len.
Rui Marques,

6
@WillshawMedia È possibile dichiarare più variabili con una singola varistruzione. Il modo in cui è scritto, in lenrealtà è mirato come suggerisci.
jondavidjohn,

90

Il modo più veloce in assoluto per scorrere 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


1
Non dimenticare di usare var(altrimenti lendiventa una variabile globale). Inoltre, consultare jsperf.com/loops per ulteriori benchmark di loop.
Mathias Bynens,

22
Il post sul blog su cui si basa questa risposta ha ormai quasi 4 anni, e molto è cambiato nei motori js in quel momento, vedi la mia risposta di seguito per un confronto aggiornato.
jondavidjohn,

1
Sono d'accordo con @jondavidjohn. Ho testato questo codice e si è rivelato meno efficiente ... Controlla jsperf.com/caching-array-length/84
victmo

La risposta sopra è quasi universalmente (su tutti i browser) molto più lenta di un for-loop. Vedi il link JSPerf nella risposta accettata. È un vero peccato, perché è estremamente leggibile IMO.
Letharion,

3
Sto indovinando @jondavidjohn che ciò che intendi per "la mia risposta sotto" è "la mia risposta sopra" lol.
Shanimal,

40

A partire da giugno 2016 , eseguendo alcuni test nell'ultimo Chrome (71% del mercato dei browser a maggio 2016 e in aumento):

  • Il ciclo più veloce è un ciclo for , sia con che senza lunghezza di cache che offre prestazioni molto simili. (Il ciclo for con lunghezza memorizzata nella cache a volte produceva risultati migliori rispetto a quello senza cache, ma la differenza è quasi trascurabile, il che significa che il motore potrebbe essere già ottimizzato per favorire lo standard e probabilmente il più semplice per loop senza cache).
  • Il ciclo while con decrementi era circa 1,5 volte più lento del ciclo for.
  • Un loop che utilizzava una funzione di callback (come lo standard forEach), era circa 10 volte più lento del loop for.

Credo che questo thread sia troppo vecchio ed è fuorviante per i programmatori pensare di aver bisogno di memorizzare nella cache la lunghezza, o usare i movimenti di attraversamento inverso con decrementi per ottenere prestazioni migliori, scrivendo codice meno leggibile e più incline agli errori di un semplice semplice ciclo. Pertanto, raccomando:

  • Se la tua app scorre su molti elementi o il tuo codice loop si trova all'interno di una funzione che viene spesso utilizzata, la risposta è un semplice ciclo:

    for (var i = 0; i < arr.length; i++) {
      // Do stuff with arr[i] or i
    }
  • Se la tua app non scorre realmente su molti elementi o devi solo fare piccole iterazioni qua e là, usare lo standard callback di ogni call o qualsiasi funzione simile dalla tua libreria JS preferita potrebbe essere più comprensibile e meno soggetto a errori, dal momento che l'ambito della variabile 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 qualche millisecondo mentre esegui l'iterazione su miliardi di righe e la lunghezza dell'array non cambia durante il processo, potresti considerare di memorizzare nella cache la lunghezza del tuo 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]
    }

No. jsbench.github.io/#67b13d4e78cdd0d7a7346410d5becf12 mostra che il più veloce è "Reverse loop, confronto implicito, codice incorporato" (105.221 ops / sec) mentre "Loop, valore memorizzato nella cache, codice incorporato" ha segnato solo 76.635 ops / sec (Chrome 38.0.2125.111 )
Fr0sT

@ Fr0sT Il benchmark è uno scenario diverso, che attraversa array dall'indice 1 a <= lunghezza. Naturalmente questo porterà a risultati diversi. Se provi a attraversare matrici a base zero con <lunghezza - il che mi sembra il solito scenario - scoprirai che i risultati sono ottimizzati meglio con un normale ciclo "for" (con una lunghezza della cache leggermente più veloce).
CGodo

Kyopaxa ha modificato i parametri di riferimento in (0 <= i <lunghezza), i risultati sono gli stessi. "Ciclo inverso, confronto implicito, chiamata di funzione" ha totalizzato 365 kops / sec, mentre "Ciclo, valore memorizzato nella cache, codice incorporato" ha totalizzato 350 kops / sec (FF 51)
Fr0sT,

@ Fr0sT se si modificano i loop-for memorizzati nella cache a base zero senza un confronto uguale, come ad esempio for(let i=0, j=array.length; i < j; i++)la velocità in avanti per i loop accelera notevolmente. In alcuni test l'ho eseguito ha vinto, nella maggior parte dei casi era nel margine di errore o nel ciclo inverso.
Isaac B

1
@IsaacB e tutto, scusate non ho notato che la panchina è abbastanza errata - tutti i loop diretti ripetono 1..lunghezza mentre i cicli inversi ripetono la lunghezza..0 (la voce arr [length] non è valida). Ho corretto i test e ora mostrano i seguenti risultati: "Loop, codice incorporato" 360.616 ops / sec ± 0,27%, "Loop, valore memorizzato nella cache, codice incorporato" 345.786 ops / sec ± 2,18% (Sic!) "Reverse loop, confronto implicito, codice incorporato "322.640 ops / sec ± 2,90% (!!!). I test sono stati eseguiti da FF51. La nuova panchina è qui jsbench.github.io/#6bdfcd2692ba80c16a68c88554281570 . Quindi sembra che non abbia senso bruciare i circuiti.
Fr0sT

31

Se l'ordine non è importante, preferisco questo stile:

for(var i = array.length; i--; )

Memorizza la lunghezza della cache ed è molto più breve da scrivere. Ma itererà sull'array in ordine inverso.


6
L'hai appena ucciso.
Vignesh Raja,

non hai bisogno di i> = 0 ;?
Marwa Ahmad

3
@MarwaAhmad: No. i--restituisce un numero e una volta che il numero è 0la condizione è falseperché Boolean(0) === false.
Felix Kling

30

È solo il 2018, quindi un aggiornamento potrebbe essere bello ...

E devo davvero essere in disaccordo con la risposta accettata . Si differenzia su diversi browser. alcuni lo fanno forEachpiù velocemente, altri for-loope alcuni while qui sono un punto di riferimento su tutti i metodi http://jsben.ch/mW36e

arr.forEach( a => {
  // ...
}

e dato che puoi vedere un sacco di for-loop come for(a = 0; ... )allora vale la pena ricordare che senza 'var' le variabili saranno definite a livello globale e questo può influenzare notevolmente la velocità, quindi rallenterà.

Il dispositivo di Duff funziona più velocemente su Opera ma non su Firefox

var arr = arr = new Array(11111111).fill(255);
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;
  });
}]
, ["for const..in (only 3.3%)", () => {
  var ar = arr.slice(0,arr.length/33);
  for( const a in ar ) {
    var b = a + 1;
  }
}]
, ["for let..in (only 3.3%)", () => {
  var ar = arr.slice(0,arr.length/33);
  for( let a in ar ) {
    var b = a + 1;
  }
}]
, ["for var..in (only 3.3%)", () => {
  var ar = arr.slice(0,arr.length/33);
  for( var a in ar ) {
    var b = a + 1;
  }
}]
, ["Duff's device", () => {
  var len = arr.length;
  var i, n = len % 8 - 1;

  if (n > 0) {
    do {
      var b = arr[len-n] + 1;
    } while (--n); // n must be greater than 0 here
  }
  n = (len * 0.125) ^ 0;
  if (n > 0) { 
    do {
      i = --n <<3;
      var b = arr[i] + 1;
      var c = arr[i+1] + 1;
      var d = arr[i+2] + 1;
      var e = arr[i+3] + 1;
      var f = arr[i+4] + 1;
      var g = arr[i+5] + 1;
      var h = arr[i+6] + 1;
      var k = arr[i+7] + 1;
    }
    while (n); // n must be greater than 0 here also
  }
}]];
function bench(title, f) {
  var t0 = performance.now();
  var res = f();
  return performance.now() - t0; // console.log(`${title} took ${t1-t0} msec`);
}
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( function(a) {
                      arr = new Array(11111111).fill(255);
                      return [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) =>
  `<div>` +
    `<span>${title} &nbsp;</span>` +
    `<span style="width:${3+n/2}%">&nbsp;${Number(time.toFixed(3))}msec</span>` +
  `</div>`;

var strRes = times.map( t => template(...t) ).join("\n") + 
            `<br><br>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;
  animation:showup .37s .111s;
  -webkit-animation:showup .37s .111s;
}
@keyframes showup { from { width:0; } }
@-webkit-keyframes showup { from { width:0; } }
<div id="container"> </div>


3
@Maykonn probabilmente volevi dire "e funziona ovunque tranne Opera Mini"
dube

3
@Maykonn Che non è elencato nella vista predefinita perché lo 0,18% di tutti gli utenti ha IE8 e non dovresti perdere tempo a cercare di supportarlo; nel 2018 è un cavallo morto.
dube,

1
È sicuramente vero se si considerano tutti gli utenti di tutto il mondo. Ma, sfortunatamente, in specifiche parti del mondo IE8 è ancora rilevante.
Maykonn,

1
Se posso, non solo diversi browser avranno risultati diversi con metodi diversi, ma gli stessi browser avranno risultati diversi con input diversi. Un enorme numero solo di array sarà molto ottimizzato, mentre un piccolo mix non lo farà.
Kaiido,

1
@Tahlil Grazie.
nullqube

19

Il 2014 Whileè tornato

Basta pensare logico.

Guarda questo

for( var index = 0 , length = array.length ; index < length ; index++ ) {

 //do stuff

}
  1. È necessario creare almeno 2 variabili (indice, lunghezza)
  2. È necessario verificare se l'indice è inferiore alla lunghezza
  3. È necessario aumentare l'indice
  4. il forloop ha 3 parametri

Ora dimmi perché questo dovrebbe essere più veloce di:

var length = array.length;

while( --length ) { //or length--

 //do stuff

}
  1. Una variabile
  2. Nessun controllo
  3. l'indice è diminuito (le macchine preferiscono quello)
  4. while ha solo un parametro

Ero totalmente confuso quando Chrome 28 ha mostrato che il ciclo for è più veloce del tempo. Questo deve avere ben una sorta di

"Uh, tutti usano il ciclo for, concentriamoci su quello quando sviluppiamo per Chrome."

Ma ora, nel 2014 il ciclo while è tornato su Chrome. è 2 volte più veloce, su altri / vecchi browser era sempre più veloce.

Ultimamente ho fatto alcuni nuovi test. Ora nel mondo reale quei codici brevi non valgono nulla e jsperf non può effettivamente eseguire correttamente il ciclo while, perché deve ricreare l'array.length che richiede anche tempo.

non è possibile ottenere la velocità effettiva di un ciclo while su jsperf.

devi creare la tua 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 / tempo di rendering / tempo di disegno o comunque tu voglia chiamarlo.

Ad esempio ho una scena su tela in cui ho bisogno di calcolare le coordinate e le collisioni ... questo avviene tra 10-200 MicroSecondi (non millisecondi). in realtà ci vogliono vari millisecondi per eseguire il rendering di tutto. Stesso come in DOM.

MA

C'è un altro modo super performante che usa il per loopin alcuni casi ... per esempio per copiare / clonare un array

for(
 var i = array.length ;
 i > 0 ;
 arrayCopy[ --i ] = array[ i ] // doing stuff
);

Si noti l'impostazione dei parametri:

  1. Come nel ciclo while sto usando solo una variabile
  2. È necessario verificare se l'indice è maggiore di 0;
  3. Come puoi vedere, questo approccio è diverso rispetto al normale per il ciclo che tutti usano, poiché faccio cose all'interno del terzo parametro e diminuisco anche direttamente all'interno dell'array.

Detto questo, ciò conferma che le macchine come il -

scrivendo che stavo pensando di renderlo un po 'più corto 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 usare ancora iuna volta rallenta tutto. È 1/5 più lento del forloop precedente e di quello precedente while.

Nota: il ;è molto importante dopo la per Looo senza{}

Anche se ti ho appena detto che jsperf non è il modo migliore per testare gli script .. ho aggiunto qui 2 loop

http://jsperf.com/caching-array-length/40

Ed ecco un'altra risposta sulle prestazioni in javascript

https://stackoverflow.com/a/21353032/2450730

Questa risposta è 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/


Questa risposta inizia molto bene . Ho notato che negli ultimi due anni è forstato più veloce del while, e una volta ho letto su crome-dev è stato esattamente per il motivo che hai citato. Sarebbe solo una questione di tempo prima di whilerecuperare di nuovo. Da quel momento in poi, la logica nella prima parte della tua risposta rimarrà (ancora una volta, sì)! Tuttavia, le implementazioni moderne non seguono più rigidamente ogni passaggio specificato dall'ecma (ottimizzano). Dal momento che ora il tuo motore non è più il collo di bottiglia più evidente, ora puoi effettivamente notare i mancati cache della CPU nei loop inversi !
GitaarLAB,

Spiega, quindi forse posso correggere la risposta o imparare qualcosa di nuovo. tra l'altro la risposta ha ormai più di un anno ... i browser potrebbero essere cambiati nel tempo come sempre ...
cocco

Secondo me, while (--length) è malvagio perché mentre funziona tecnicamente perché 0 è falso, 0 e falso non sono veramente la stessa cosa semanticamente parlando.
scott.korin,

sì ... è un post più vecchio ora ... ma sì, adoro la semplicità del tempo. E di sicuro mentre lo menzioni in entrambi i casi devi sapere cosa scrivere. Dall'altro lato non ho mai avuto la necessità di passare in rassegna numeri negativi.
cocco,

9
"macchine preferiscono questo" suona come una frase di un annuncio per un detersivo per bucato
CocoaBean

11

http://jsperf.com/caching-array-length/60

L'ultima revisione del test, che ho preparato (riutilizzando quella precedente), mostra una cosa.

La lunghezza della cache non è molto importante, ma non danneggia.

Ogni prima esecuzione del test collegata sopra (nella scheda appena aperta) fornisce i migliori risultati per gli ultimi 4 frammenti (3 °, 5 °, 7 ° e 10 ° nelle classifiche) in Chrome, Opera e Firefox nel mio Debian Squeeze 64-bit (il mio hardware desktop ). Le esecuzioni successive danno risultati piuttosto diversi.

Le conclusioni dal punto di vista delle prestazioni sono semplici:

  • Vai con per loop (avanti) e prova usando !==invece di <.
  • Se non è necessario riutilizzare l'array in un secondo momento, shift()è efficace anche il loop su lunghezza ridotta e l' array distruttivo .

tl; dr

Al giorno d'oggi (2011.10) il modello sotto sembra essere il più veloce.

for (var i = 0, len = arr.length; i !== len; i++) {
    ...
}

Tieni presente che la memorizzazione nella cache arr.lengthnon è cruciale qui, quindi puoi solo testare i !== arr.lengthe le prestazioni non diminuiranno, ma otterrai un codice più breve.


PS: So che in snippet con il shift()suo risultato potrebbe essere usato invece di accedere allo 0 ° elemento, ma in qualche modo l'ho trascurato dopo aver riutilizzato la revisione precedente (che aveva errori durante i loop), e in seguito non volevo perdere risultati già ottenuti.


La creazione di variabili all'interno del ciclo come let current = arr [i] può ridurre una prestazione (allocazione di memoria elevata)? O sarebbe meglio dichiarare corrente prima del ciclo? Oppure usa arr [i] in tutti i punti all'interno del loop?
Makarov Sergey,

8

"Il migliore" come nelle prestazioni pure? o prestazioni E leggibilità?

La prestazione "migliore" è questa, che utilizza una cache e l'operatore 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 for-loop senza cache è il miglior equilibrio tra tempo di esecuzione e tempo di lettura del programmatore. Ogni programmatore che ha iniziato con C / C ++ / Java non sprecherà un ms dovendo leggere questo

for(var i=0; i < arr.length; i++){
  // blah blah
}

2
+1 per leggibilità. Non importa quanto bene lensia chiamato, si dovrebbe sempre fare un doppio giro su quel primo ciclo. L'intenzione del secondo ciclo è ovvia.
Josh Johnson,

7

** memorizza nella cache la lunghezza dell'array all'interno del loop, alcuni secondi di tempo verranno elusi. Dipende dagli elementi nell'array se ci sono più elementi nell'array c'è una grande differenza rispetto al tempo *

**

sArr; //Array[158];

for(var i = 0 ; i <sArr.length ; i++) {
 callArray(sArr[i]); //function call
}

***end: 6.875ms***

**

**

sArr; //Array[158];
for(var i = 0,len = sArr.length ; i < len ; i++) {
  callArray(sArr[i]); //function call
}

***end: 1.354ms***

**


6

Questo sembra essere di gran lunga il modo più veloce ...

var el;
while (el = arr.shift()) {
  el *= 2;
}

Tieni presente che ciò consumerà l'array, lo mangerà e non lascerà nulla ...


2
arr.shift();anziché in arr.pop() tal modo è possibile evitare l'inversione dell'array.
Tintu C Raju,

1
@Gargaroz se stai ricevendo un JSON da un servizio web, ad esempio un servizio di chat o articoli in un catalogo prodotti. Un'altra situazione in cui è sufficiente utilizzare una volta l'array può essere ad esempio un grafico che ottiene molte coordinate su base periodica. Ci sono molti esempi
Sergio,

Bene, grazie per la spiegazione, molto gentile da parte tua; puoi indicarmi la direzione in cui potrei trovare ulteriori esempi per sfruttare questo tipo di loop?
Gargaroz,

1
Attualmente in Chrome 53 e Firefox 48 è uno degli approcci più lenti - controlla su perfjs.info/array-iteration
Pencroff

1
@Alireza sono d'accordo, ho un commento anche per quello nella mia risposta.
Sergio,

4

È l'anno 2017 .

Ho fatto alcuni test.

https://jsperf.com/fastest-way-to-iterate-through-an-array/

Sembra che il whilemetodo sia il più veloce su Chrome.

Sembra che il decremento sinistra ( --i) è molto più veloce rispetto agli altri ( ++i, i--,i++ ) su Firefox.

Questo approccio è in media il digiuno. 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;
}

3
Utilizzando la parola chiave, letsi stanno effettivamente confrontando le prestazioni di creazione dell'ambito anziché le prestazioni del ciclo. L'uso let i = 0, ii = array.lengthnei forloop creerà un nuovo ambito per quelle variabili all'interno del forblocco. I tuoi whileesempi non creano un nuovo ambito per le variabili all'interno del whileblocco ed è per questo che sono più veloci. Se usi varinvece che letnei tuoi cicli for, vedrai come i loop sono ancora veloci come quelli del 2017, ma più leggibili.
CGodo

Ecco un jsperf di ciò di cui sto parlando: jsperf.com/javascript-loop-testing-let-vs-var
CGodo

Questo è solo un problema in Chrome. In altri browser vare lethanno le stesse prestazioni - stackoverflow.com/a/32345435/1785975
SeregPie

Interessante. Ad ogni modo, non trovo whileaccurata l'affermazione di " essere più veloci in Chrome". È solo se utilizzato a letcausa di problemi di prestazioni di quella parola chiave in Chrome. Se si utilizza varo con altri browser fore whilesono praticamente uguali, a volte forè ancora più veloce a seconda del benchmark ed è un imho più compatto e leggibile.
CGodo

2

Scrivo sempre nel primo stile.

Anche se un compilatore è abbastanza intelligente da ottimizzarlo per le matrici, ma è comunque intelligente se stiamo usando DOMNodeList qui o qualche oggetto complicato con lunghezza calcolata?

So qual è la domanda sugli array, ma penso che sia una buona pratica scrivere tutti i tuoi loop in un unico stile.


1
var arr = []; // The array
var i = 0;
while (i < arr.length) {
    // Do something with arr[i]
    i++;
}

i ++ è più veloce di ++ i, --i e i--

Inoltre, puoi salvare l'ultima riga facendo arr [i ++] l'ultima volta che devi accedere a i (ma può essere difficile eseguire il debug).

Puoi provarlo qui (con altri test di loop): http://jsperf.com/for-vs-whilepop/5


1
Attualmente in Chrome 53 è vero, ma Firefox 48 ha la stessa velocità - controlla su perfjs.info/array-iteration
Pencroff


1

A partire da settembre 2017 questi test jsperf mostrano che il modello seguente è il più performante su Chrome 60:

function foo(x) {
 x;
};
arr.forEach(foo);

Qualcuno è in grado di riprodurre?


Sì, sembra essere più veloce, tuttavia prova a eseguirlo in IE11 e quelle opzioni sono le più lente. E in Firefox 55.03 la "vecchia cache in cache" sta arrivando a 12mil, una prestazione sbalorditiva rispetto ai 3.3k di Chrome. Per garantire prestazioni costanti in tutti i browser, è necessario utilizzare il ciclo medio più veloce per ogni browser.
Plippie,

0

Ho provato alcuni altri modi per eseguire l'iterazione di un array enorme e ho scoperto che dimezzare la lunghezza dell'array e iterare entrambe le metà in un singolo loop è più veloce. Questa differenza di prestazioni può essere vista durante l'elaborazione di array di grandi dimensioni .

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

Qualche confronto delle prestazioni (usando timer.js) tra la lunghezza memorizzata nella cache per il ciclo VS il metodo sopra.

http://jsfiddle.net/tejzpr/bbLgzxgo/




0

Mentre il ciclo è un po 'più veloce rispetto al ciclo.

var len = arr.length;
while (len--) {
    // blah blah
}

Usa invece il ciclo while



-1

La soluzione più elegante che conosco è usare la mappa.

var arr = [1,2,3];
arr.map(function(input){console.log(input);});

46
La domanda non è quella di chiedere il modo più lento per scorrere un ciclo
eoleary,

-1

Prova questo:

var myarray =[],
i = myarray.lenght;
while(i--){
// do somthing
}

-1

Il modo più rapido per eseguire il loop in un array è utilizzare il filtro. Il metodo filter () crea un nuovo array con tutti gli elementi che superano il test implementato dalla funzione fornita.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

const words = ['Floccinaucinihilipilification', 'limit', 'elite', 'Hippopotomonstrosesquipedaliophobia', 'destruction', 'present'];

const result = words.filter(word => word.length > 6);

console.log(new Date(), result);

Dalla mia esperienza, preferisco sempre filtri, mappe ecc.


La domanda riguarda l'iterazione sull'array nel minor tempo possibile e non la copia dell'array in un nuovo array.
Rahul Kadukar il

-1

Dal 2019 WebWorker è diventato più popolare, per set di dati di grandi dimensioni, possiamo utilizzare WebWorker per elaborare molto più rapidamente utilizzando pienamente i processori multi-core.

Abbiamo anche Parallel.js che rende WebWorker molto più facile da usare per l'elaborazione dei dati.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.