Best practice per l'iterazione in JavaScript
Questo articolo spiega le best practice per l'iterazione in JavaScript.
YouTube Video
Best practice per l'iterazione in JavaScript
In JavaScript, è comune utilizzare i cicli for
per l'iterazione. Qui forniremo una spiegazione dettagliata delle best practice per utilizzare i cicli for
per scrivere codice efficiente e leggibile.
Scegli la struttura di ciclo più adatta
JavaScript fornisce diversi costrutti di ciclo, ciascuno adatto per scopi diversi.
1// Example of a for loop
2for (let i = 0; i < 5; i++) {
3 console.log(i);
4}
5
6// Example of a for...of loop
7const array = [10, 20, 30];
8for (const value of array) {
9 console.log(value);
10}
11
12// Example of a for...in loop
13const obj = { a: 1, b: 2, c: 3 };
14for (const key in obj) {
15 console.log(`${key}: ${obj[key]}`);
16}
17
18// Example of a while loop
19let count = 0;
20while (count < 5) {
21 console.log(count);
22 count++;
23}
- L'istruzione
for
è adatta quando il numero di iterazioni è predeterminato. - L'istruzione
for...of
è adatta per elaborare in modo conciso array e oggetti iterabili. - L'istruzione
for...in
viene utilizzata per iterare sulle proprietà di un oggetto. Tuttavia, non è adatto per gli array. - Le istruzioni
while
edo...while
vengono utilizzate per controllare i cicli in base a condizioni.
Utilizzo del metodo forEach
e dell'istruzione for...of
.
Durante l'iterazione di un array, è comune utilizzare un'istruzione for
per accedere all'indice, ma il metodo forEach
o l'istruzione for...of
possono essere più leggibili.
1// Using a standard for loop
2const array = ["apple", "banana", "cherry"];
3for (let i = 0; i < array.length; i++) {
4 console.log(array[i]);
5}
6
7// Using forEach
8array.forEach(item => console.log(item));
9
10// Using for...of
11for (const item of array) {
12 console.log(item);
13}
- L'istruzione
for
consente una gestione esplicita degli indici durante l'iterazione. - Il metodo
forEach
utilizza una funzione di callback per elaborare ciascun elemento in modo conciso. - L'istruzione
for...of
è altamente leggibile e consente l'accesso diretto a ciascun elemento di un array.
Ottimizza le condizioni del ciclo
Poiché la condizione del ciclo viene valutata ripetutamente, evitare calcoli non necessari può migliorare le prestazioni.
1const names = ["Alice", "Bob", "Charlie"];
2const scores = [85, 92, 78];
3
4// Inefficient example
5for (let i = 0; i < Math.min(names.length, scores.length); i++) {
6 console.log(`${names[i]} scored ${scores[i]}`);
7}
8
9// Efficient example
10for (let i = 0, len = Math.min(names.length, scores.length); i < len; i++) {
11 console.log(`${names[i]} scored ${scores[i]}`);
12}
- Come mostrato in questo esempio, memorizzare il risultato del calcolo in una variabile in anticipo consente un'esecuzione del ciclo più efficiente.
1const scores = [85, 92, 78];
2let sum = 0;
3let sum2 = 0;
4
5// Inefficient example
6for (let i = 0; i < scores.length; i++) {
7 sum += scores[i];
8}
9console.log(`Total score : ${sum}`);
10
11// Efficient example
12for (let i = scores.length - 1; i >= 0; i--) {
13 sum2 += scores[i];
14}
15console.log(`Total score : ${sum2}`);
- Come mostrato in questo esempio, invertire la condizione può talvolta essere più efficiente.
Ottimizzazione dell'elaborazione dei cicli
Poiché l'elaborazione dei cicli viene eseguita ripetutamente, evitare calcoli inutili può migliorare le prestazioni.
1const array = ["apple", "banana", "cherry"];
2
3// Inefficient example
4for (let i = 0; i < 100; i++) {
5 const element = document.querySelector("#myElement");
6 element.textContent = `Count: ${i}`;
7}
8
9// Efficient example
10const element = document.querySelector("#myElement");
11for (let i = 0; i < 100; i++) {
12 element.textContent = `Count: ${i}`;
13}
- In questo esempio, spostando il metodo
querySelector
fuori dal ciclo, si eliminano calcoli inutilmente ripetuti.
Fai attenzione all’ambito delle variabili
Usa let
o const
per garantire che le variabili all'interno del ciclo abbiano l'ambito appropriato. Dato che var
è limitato all’ambito delle funzioni, potrebbe causare comportamenti imprevisti.
1// Using let
2for (let i = 0; i < 3; i++) {
3 console.log(i);
4}
5
6// Potential issue with var
7for (var i = 0; i < 3; i++) {
8 setTimeout(() => console.log(i), 1000); // 3, 3, 3
9}
10
11// Using let to avoid the issue
12for (let i = 0; i < 3; i++) {
13 setTimeout(() => console.log(i), 1000); // 0, 1, 2
14}
var
ha uno scope di funzione, quindi dopo il cicloi
è pari a3
e tutte le funzioni eseguite dasetTimeout
restituiranno3
.- Utilizzando
let
, l'i
all'interno della funzione di callback disetTimeout
si riferisce a un nuovo valore per ogni ciclo, quindi0, 1, 2
vengono stampati come previsto.
Migliora la leggibilità con interruzioni anticipate
Per semplificare l'elaborazione dei cicli, usa break
e continue
in modo appropriato per migliorare la leggibilità.
1// Example using break
2for (let i = 0; i < 10; i++) {
3 if (i === 5) {
4 break; // Exit the loop
5 }
6 console.log(i);
7}
8
9// Example using continue
10for (let i = 0; i < 10; i++) {
11 if (i % 2 === 0) {
12 continue; // Skip to the next iteration
13 }
14 console.log(i);
15}
- Utilizzando
break
è possibile interrompere l'elaborazione del ciclo a metà, saltando tutte le iterazioni successive. - Utilizzando
continue
è possibile saltare l'elaborazione corrente del ciclo e passare all'iterazione successiva.
Evita annidamenti profondi
Gli annidamenti profondi rendono il codice più difficile da leggere, quindi cerca di mantenere gli annidamenti superficiali utilizzando ritorni anticipati o suddividendo le funzionalità in funzioni separate.
1// Deeply nested example
2for (let i = 0; i < 5; i++) {
3 for (let j = 0; j < 5; j++) {
4 if (i + j > 5) {
5 console.log(i, j);
6 }
7 }
8}
9
10// Improved using function decomposition
11function processPairs(i) {
12 for (let j = 0; j < 5; j++) {
13 if (i + j > 5) {
14 console.log(i, j);
15 }
16 }
17}
18
19for (let i = 0; i < 5; i++) {
20 processPairs(i);
21}
- In questo esempio, le funzioni vengono utilizzate per ridurre l'annidamento.
Prendi in considerazione la gestione degli errori
Se esiste la possibilità che si verifichino errori all'interno del ciclo, implementa una corretta gestione degli errori.
1const data = ["123", "abc", "456", "xyz"];
2
3// Without Error Handling
4for (const item of data) {
5 const result = parseInt(item);
6 console.log(`Parsed value: ${result}`);
7}
8
9// With Error Handling
10for (const item of data) {
11 try {
12 const result = parseInt(item);
13 if (isNaN(result)) {
14 throw new Error(`Invalid number: ${item}`);
15 }
16 console.log(`Parsed value: ${result}`);
17 } catch (error) {
18 console.error(`Error processing item: ${item}. ${error.message}`);
19 }
20}
- In questo esempio, la gestione degli errori viene eseguita per elaborare dati non validi, rilevando e segnalando eventuali problemi.
Punti da notare nella gestione asincrona
Quando si gestisce l'elaborazione asincrona nei cicli, l'uso di async/await
può portare a un codice conciso e intuitivo.
1const urls = ["https://example.com/1", "https://example.com/2"];
2
3// Proper handling of asynchronous operations
4async function fetchUrls() {
5 for (const url of urls) {
6 const response = await fetch(url);
7 const data = await response.json();
8 console.log(data);
9 }
10}
11
12fetchUrls();
- Questo codice recupera in modo asincrono gli URL dall'array
urls
uno per uno ed elabora i risultati in formato JSON. L'utilizzo diasync/await
semplifica le operazioni asincrone, recuperando sequenzialmente i dati per ogni URL e stampandoli nella console.
Comprendi la differenza tra l'istruzione for...of
e forEach()
nell'elaborazione asincrona.
1async function asyncTask(num) {
2 return new Promise(resolve => {
3 setTimeout(() => {
4 console.log(`Task ${num} done`);
5 resolve();
6 }, 100);
7 });
8}
9
10async function runWithForOf() {
11 console.log("Start for...of");
12 for (const num of [1, 2, 3]) {
13 await asyncTask(num);
14 }
15 console.log("End for...of");
16}
17
18async function runWithForEach() {
19 console.log("Start forEach");
20 [1, 2, 3].forEach(async num => {
21 await asyncTask(num);
22 });
23 console.log("End forEach");
24}
25
26async function executeExamples() {
27 await runWithForOf();
28 await runWithForEach();
29}
30
31executeExamples();
-
Quando gestisci l'elaborazione asincrona nei cicli, nota le differenze di comportamento, come mostrato in questo esempio, tra l'uso di
for...of
conasync/await
e l'uso diforEach()
. -
Con
for...of
, il codice viene eseguito in modo sequenziale e aspetta alawait
all'interno del ciclo prima di passare all'iterazione successiva. D'altra parte,forEach()
esegue l'elaborazione in parallelo.
Conclusione
L'istruzione for
in JavaScript è uno strumento semplice ma potente. Seguendo le migliori pratiche introdotte qui, puoi scrivere codice efficiente e altamente leggibile. Fai attenzione a scegliere costrutti di ciclo appropriati, alla gestione dello scope, alla gestione degli errori e punta a scrivere codice altamente mantenibile.
Puoi seguire l'articolo sopra utilizzando Visual Studio Code sul nostro canale YouTube. Controlla anche il nostro canale YouTube.