2011-12-31 10 views
38

Dato questo codicePerché l'iterazione attraverso una serie avanti più velocemente allora in avanti

var arr = []; 
    for (var i = 0; i < 10000; ++i) { 
     arr.push(1); 
    } 

Attaccanti

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

indietro

for (var i = arr.length - 1; i >= 0; --i) {; 
} 

hard coded F orward

for (var i = 0; i < 10000; ++i) {; 
} 

perché il backwords è molto più veloce?

Qui è la prova http://jsperf.com/array-iteration-direction

+6

Nota che la tua inversione del caso dovrebbe iniziare a 'arr.length-1' e avere 'i> = 0' piuttosto che' i> 0'. – nnnnnn

+1

Il titolo è fuorviante. Non è più il caso che usare direttamente arr.length * è * più lento nei browser avanzati. – user2864740

+0

possibile duplicato di [prestazioni del ciclo JavaScript - Perché decrementare l'iteratore verso 0 più velocemente dell'incremento] (http://stackoverflow.com/q/3520688/1048572) – Bergi

risposta

63

Poiché l'avanti-condizione deve ricevere la proprietà length dell'array ogni volta, mentre l'altra condizione ha solo per verificare "maggiore di zero", un compito molto veloce.

Quando la lunghezza della matrice non cambia durante il ciclo, e davvero guardare ns-perfomance, è possibile utilizzare

for (var i=0, l=arr.length; i<l; i++) 

BTW: Invece di for (var i = arr.length; i > 0; --i) si potrebbe utilizzare for (var i = arr.length; i-- > 0;) che corre proprio attraverso l'array da n-1 a 0, non da n a 1.

+0

Sì, questo è il modo in cui lo faccio per le funzioni ottimizzate. Basta notare che se l'array è mutabile (e di solito non lo è), questo potrebbe saltare una o due risorse. Ad esempio, questo non funzionerà se stai eseguendo il looping di elementi che il loop stesso sta aggiungendo o eliminando. –

+3

si può anche fare 'for (...; i--;)' – ajax333221

+0

quindi in pratica significa che se non cambio l'array e tengo array.length in una variabile, quindi retrocedero = velocità avanti? Esempio: var length = array.length; per (var i = 0; i

8

Perché nel primo modulo si accede alla proprietà length dell'array arr una volta per ogni iterazione, mentre nel secondo si fa solo una volta.

+0

@samccone - quale risultato si vede (quale test in cui browser)? Vedo che la memorizzazione nella cache della lunghezza è sempre almeno altrettanto veloce e solitamente più veloce. – jfriend00

+0

okay, hai ragione ... sembra che sia davvero un miscuglio di risultati ma il caching lo aiuta ... grazie XD – samccone

2

i > 0 è più veloce di i < arr.length e si verifica a ogni iterazione del ciclo.

è possibile attenuare la differenza con questo:

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

Questo non è ancora veloce come la voce indietro, ma più velocemente di quanto la vostra opzione in avanti.

+0

guarda il test codificato http://jsperf.com/array-iteration-direction ... usando la tua logica dovrebbe essere più veloce no? – samccone

5

Se si desidera avere lo stesso ritmo, è possibile farlo per l'iterazione di inoltro;

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

Così, lo script non avrà bisogno di prendere la lunghezza della matrice su everystep.

+0

Ahhh ... interessante il tuo metodo ora prende la corona per l'iterazione più veloce http://jsperf.com/array-iteration-direction – samccone

1

E questi sono altrettanto buone:

var arr= [], L= 10000; 
while(L>-1) arr[L]= L--; 

O

var arr= [], i= 0; 
while(i<10001) arr[i]=i++; 
+0

hahaha ingannevole e ingannevole – samccone

+0

Dovrebbe essere "while (- L> = 0) arr [L] = L; ' –

4

Non sono del tutto sicuro di questo, ma qui è la mia ipotesi:

Per il seguente codice:

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

D Durante il runtime, c'è un calcolo di arr.length dopo ogni loop pass. Questa può essere un'operazione banale quando è isolata, ma può avere un impatto quando si tratta di array multipli/enormi. Si può provare il seguente:

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

Nel codice precedente, si calcola la lunghezza della matrice sola volta, e operare con quel numero calcolato, invece di eseguire il calcolo lunghezza più e più volte.

Ancora una volta, sto solo mettendo i miei pensieri qui. Osservazione interessante davvero!

1

farlo come di seguito, si esibirà nello stesso modo.perché arr.length richiede tempo in ogni iterazione in avanti.

int len = arr.length; 

avanti

for (var i = 0; i < len; ++i) { 
} 

all'indietro

for (var i = len; i > 0; --i) { 
} 
+0

Il caso all'indietro non è corretto. Quello che faccio è 'for (i = len; --i> = 0;) {' –