Efficienza Javascript: "for" vs "forEach" [chiuso]


103

Qual è lo standard attuale nel 2017 in Javascript con i cicli for () rispetto a un .forEach.

Attualmente sto lavorando la mia strada attraverso Colt Steeles "Web Dev Bootcamp", a Udemy e lui favori forEachsopra fornei suoi insegnamenti. Tuttavia, ho cercato varie cose durante gli esercizi come parte del lavoro del corso e trovo sempre più consigli per usare un forloop piuttosto che forEach. La maggior parte delle persone sembra affermare che il ciclo for è più efficiente.

È qualcosa che è cambiato da quando è stato scritto il corso (intorno al 2015) o sono i loro veri pro e contro per ciascuno, che si imparerà con più esperienza.

Qualsiasi consiglio sarebbe molto apprezzato.


11
Perché legarti all'idea soggettiva di qualcuno di uno standard del 2017? Adottare uno standard senza tempo, come scrivere codice pulito e manutenibile, sapendo che gli ingegneri stanno lavorando duramente per rendere i costrutti più comunemente usati molto efficienti, e quindi ottimizzare le prestazioni quando si ha un problema di prestazioni specifico

2
Un nativo forè difficile da battere per pura velocità. forEach()invoca un callback per ogni iterazione; quindi, questo ovviamente porta con sé un po 'di overhead.
canonico

1
essendo uno sviluppatore per cui uso raramente o per ciascuno di essi, la maggior parte del lavoro viene svolto mediante metodi di mappatura, filtro o riduzione.
AT

12
@AT fintanto che non sei uno di quei ragazzi che usa mapesclusivamente per l'iterazione e scarta il nuovo array che genera. Non so quante persone ho dovuto correggere su quella particolare scelta di funzione solo su questo sito.
canonico

1
@canon concorda, la selezione del loop è importante e si dovrebbe tenere a mente l'output e i residui di tali metodi durante la scelta. Credo che per la leggibilità dovrebbe essere evitato il semplice "for loops".
AT

Risposte:


201

per

fori cicli sono molto più efficienti. È un costrutto di ciclo progettato specificamente per iterare mentre una condizione è vera , offrendo allo stesso tempo un meccanismo a passi (generalmente per aumentare l'iteratore). Esempio:

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

Questo non vuol dire che for -loops sarà sempre più efficiente, ma solo che i motori JS ei browser li hanno ottimizzati per esserlo. Nel corso degli anni ci sono stati compromessi su quale costrutto di looping fosse più efficiente (for, while, reduce, reverse-while, ecc.) - diversi browser e motori JS hanno le proprie implementazioni che offrono metodologie differenti per produrre gli stessi risultati. Poiché i browser ottimizzano ulteriormente per soddisfare le esigenze di prestazioni, teoricamente [].forEachpotrebbe essere implementato in modo tale da essere più veloce o paragonabile a un file for.

Benefici:

  • efficiente
  • terminazione anticipata del ciclo (onori breake continue)
  • controllo delle condizioni ( i<npuò essere qualsiasi cosa e non è vincolato alla dimensione di un array)
  • scoping variabile ( var irimane idisponibile dopo la fine del ciclo)

per ciascuno

.forEachsono metodi che eseguono l'iterazione principalmente su array (anche su altri enumerabili, come Mape Setoggetti). Sono più recenti e forniscono un codice soggettivamente più facile da leggere. Esempio:

[].forEach((val, index)=>{
   ...
});

Benefici:

  • non implica l'impostazione delle variabili (itera su ogni elemento dell'array)
  • funzioni / funzioni-freccia fanno l'ambito della variabile al blocco
    Nell'esempio sopra, valsarebbe un parametro della funzione appena creata. Pertanto, qualsiasi variabile chiamata valprima del ciclo manterrebbe i propri valori dopo la fine.
  • soggettivamente più manutenibile in quanto potrebbe essere più facile identificare ciò che il codice sta facendo - iterando su un enumerabile; mentre un ciclo for potrebbe essere utilizzato per qualsiasi numero di schemi di loop

Prestazione

La performance è un argomento delicato, che generalmente richiede una certa esperienza quando si tratta di previdenza o approccio. Al fine di determinare in anticipo (durante lo sviluppo) quanta ottimizzazione può essere richiesta, un programmatore deve avere una buona idea dell'esperienza passata con il caso problema, nonché una buona comprensione delle potenziali soluzioni.

L'uso di jQuery in alcuni casi potrebbe essere troppo lento a volte (uno sviluppatore esperto potrebbe saperlo), mentre altre volte potrebbe non essere un problema, nel qual caso la conformità cross-browser della libreria e la facilità di eseguire altre funzioni (ad esempio, AJAX, gestione degli eventi) varrebbe il tempo risparmiato per lo sviluppo (e la manutenzione).

Un altro esempio è che, se le prestazioni e l'ottimizzazione fossero tutto, non ci sarebbe altro codice oltre alla macchina o all'assembly. Ovviamente non è così in quanto ci sono molti linguaggi diversi di alto e basso livello, ciascuno con i propri compromessi. Questi compromessi includono, ma non sono limitati a, specializzazione, facilità e velocità di sviluppo, facilità e velocità di manutenzione, codice ottimizzato, codice privo di errori, ecc.

Approccio

Se non hai una buona comprensione se qualcosa richiederà un codice ottimizzato, è generalmente una buona regola pratica scrivere prima codice gestibile. Da lì, puoi testare e individuare ciò che richiede maggiore attenzione quando è necessario.

Detto questo, alcune ovvie ottimizzazioni dovrebbero far parte della pratica generale e non richiedere alcun pensiero. Ad esempio, considera il seguente ciclo:

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

Per ogni iterazione del ciclo, JavaScript recupera le arr.lengthoperazioni di determinazione dei costi di ricerca chiave su ogni ciclo. Non c'è motivo per cui questo non dovrebbe essere:

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

Questo fa la stessa cosa, ma recupera solo arr.lengthuna volta, memorizzando nella cache la variabile e ottimizzando il codice.


25
Risposta eccellente, completa, non presuntuosa, non vincolata a un singolo punto nel tempo, implementazione o test micro-benchmark.

1
Perfetto, è esattamente quello che stavo cercando e dà molta più profondità di quanto possa fare il video. Lo apprezzo molto, essendo nuovo c'è così tanto da imparare e queste sono le cose che è facile saltare semplicemente favorendo l'una sull'altra senza motivo che potrebbe ostacolarti in futuro. Grazie molto!
tonyrobbins

2
for-loop ha spesso un vantaggio in termini di debugging: sono banali in cui entrare, breakpoint e ispezionare. Con forEach () il livello di callback extra può complicare un po 'le cose.
Eric Grange

1
@FelipeBuccioni grazie, in realtà stavo per esaminarlo perché penso che i motori ora controllino se un array sarebbe stato modificato per determinare se la lunghezza è stata memorizzata nella cache. Tuttavia, per scopi legacy, penso che i motori di ottimizzazione non fossero così generosi e la lunghezza è stata un colpo di prestazioni su ogni iterazione. Darò un'occhiata al tuo articolo e lo incorporerò nella risposta quando avrò tempo, o si spera che un membro eccezionale della comunità apporti un emendamento come modifica per me :)
vol7ron

6
Mi piace molto la spiegazione in questa risposta e la frase [...], if performance and optimization was everything, there would be no other code than machine or assembly.. Credo che con l' letistruzione per la dichiarazione di una variabile locale con ambito di blocco, il secondo vantaggio di forEachnon sia più un vantaggio rispetto al forciclo a meno che in un ambiente senza supporto per let.
user7393973
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.