Najlepsze praktyki iteracji w JavaScript

Najlepsze praktyki iteracji w JavaScript

Ten artykuł wyjaśnia najlepsze praktyki iteracji w JavaScript.

YouTube Video

Najlepsze praktyki iteracji w JavaScript

W JavaScript powszechnie używa się pętli for do iteracji. Tutaj przedstawimy szczegółowe wyjaśnienie najlepszych praktyk używania pętli for do pisania wydajnego i czytelnego kodu.

Wybierz odpowiednią strukturę pętli

JavaScript oferuje wiele konstrukcji pętli, z których każda jest odpowiednia do innych celów.

 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}
  • Instrukcja for jest odpowiednia, gdy liczba iteracji jest z góry określona.
  • Instrukcja for...of jest odpowiednia do zwięzłego przetwarzania tablic i obiektów iterowalnych.
  • Instrukcja for...in służy do iteracji po właściwościach obiektu. Jednak nie nadaje się do tablic.
  • Instrukcja while i do...while są używane do kontrolowania pętli na podstawie warunków.

Wykorzystanie metody forEach oraz instrukcji for...of.

Podczas iteracji po tablicy często stosuje się instrukcję for do uzyskania dostępu do indeksu, ale metoda forEach lub instrukcja for...of mogą być bardziej czytelne.

 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}
  • Instrukcja for umożliwia jawne zarządzanie indeksami podczas iteracji.
  • Metoda forEach wykorzystuje funkcję zwrotną do zwięzłego przetwarzania każdego elementu.
  • Instrukcja for...of jest bardzo czytelna i zapewnia bezpośredni dostęp do każdego elementu w tablicy.

Optymalizuj warunki pętli

Ponieważ warunek pętli jest wielokrotnie oceniany, unikanie niepotrzebnych obliczeń może poprawić wydajność.

 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}
  • Jak pokazano w tym przykładzie, przechowywanie wyniku obliczeń w zmiennej wcześniej pozwala na bardziej wydajne wykonywanie pętli.
 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}`);
  • Jak pokazano w tym przykładzie, odwrócenie warunku może czasami być bardziej efektywne.

Optymalizacja przetwarzania pętli

Ponieważ przetwarzanie pętli jest wykonywane wielokrotnie, unikanie niepotrzebnych obliczeń może poprawić wydajność.

 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}
  • W tym przykładzie, przenosząc metodę querySelector poza pętlę, eliminowane są zbędne powtarzające się obliczenia.

Zwróć uwagę na zasięg

Używaj let lub const, aby upewnić się, że zmienne w pętli mają odpowiedni zasięg. Ponieważ var jest ograniczony do zakresu funkcji, może powodować nieoczekiwane zachowanie.

 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 ma zakres funkcji, więc po zakończeniu pętli i wynosi 3, a wszystkie funkcje wykonane przez setTimeout zwracają 3.
  • Używając let, zmienna i wewnątrz funkcji zwrotnej setTimeout odnosi się do nowej wartości dla każdej iteracji pętli, więc 0, 1, 2 są zwracane zgodnie z oczekiwaniami.

Popraw czytelność, stosując wczesne zakończenia

Aby uprościć przetwarzanie pętli, odpowiednio używaj break i continue, aby poprawić czytelność.

 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}
  • Użycie break pozwala zakończyć przetwarzanie pętli w trakcie, pomijając wszystkie kolejne iteracje.
  • Użycie continue pozwala pominąć aktualny przebieg pętli i przejść do kolejnej iteracji.

Unikaj głębokiego zagnieżdżania

Głębokie zagnieżdżenie utrudnia czytanie kodu, dlatego staraj się ograniczyć zagnieżdżenie, stosując wczesne zakończenia lub dzieląc funkcjonalność na funkcje.

 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}
  • W tym przykładzie funkcje są używane do zmniejszenia zagnieżdżeń.

Rozważ obsługę błędów

Jeśli istnieje możliwość wystąpienia błędów w pętli, zaimplementuj odpowiednią obsługę błędów.

 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}
  • W tym przykładzie obsługiwane są błędy w celu przetwarzania nieprawidłowych danych, wykrywania i zgłaszania problemów.

Punkty do zanotowania w przetwarzaniu asynchronicznym

Podczas obsługi przetwarzania asynchronicznego w pętlach, użycie async/await może prowadzić do zwięzłego i intuicyjnego kodu.

 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();
  • Ten kod asynchronicznie pobiera adresy URL z tablicy urls jeden po drugim i przetwarza wyniki w formacie JSON. Użycie async/await upraszcza operacje asynchroniczne, sekwencyjnie pobierając dane dla każdego adresu URL i wyświetlając je w konsoli.

Zrozum różnicę między instrukcją for...of a metodą forEach() w przetwarzaniu asynchronicznym.

 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();
  • Podczas obsługi przetwarzania asynchronicznego w pętlach, zwróć uwagę na różnice w zachowaniu, jak pokazano w tym przykładzie, między użyciem for...of z async/await a metodą forEach().

  • W przypadku for...of kod jest wykonywany sekwencyjnie i czeka na await wewnątrz pętli przed przejściem do kolejnej iteracji. Natomiast metoda forEach() wykonuje przetwarzanie równolegle.

Wnioski

Instrukcja for w JavaScript to proste, ale bardzo potężne narzędzie. Wykorzystując przedstawione tutaj najlepsze praktyki, możesz pisać wydajny i łatwo czytelny kod. Zwróć uwagę na wybór odpowiednich konstrukcji pętli, zarządzanie zakresem, obsługę błędów i dąż do pisania kodu łatwego w utrzymaniu.

Możesz śledzić ten artykuł, korzystając z Visual Studio Code na naszym kanale YouTube. Proszę również sprawdzić nasz kanał YouTube.

YouTube Video