Klasyczna pętla for
Gdy wiesz, ile razy chcesz coś powtórzyć, narzędziem jest pętla for. Mieści trzy części pętli z licznikiem, czyli start, stop i krok, w jednej linii nagłówka.
Pięć iteracji, pięć linii wyjścia. Czytamy nagłówek:
let i = 0wykonuje się raz, przed rozpoczęciem pętli. Ustawia licznik.i < 5jest sprawdzane przed każdą iteracją. Jeśli dajetrue, wykonuje się ciało pętli. Jeślifalse, pętla się kończy.i++wykonuje się po każdej iteracji, tuż przed ponownym sprawdzeniem warunku.
Trzy części oddziela się średnikami, a nie przecinkami. Wszystkie trzy są opcjonalne, ale pomijanie ich zdarza się rzadko: w takiej sytuacji zwykle sięga się raczej po while.
Jak te części do siebie pasują
Warto raz prześledzić pętlę ręcznie, żeby utrwalić kolejność:
Krok po kroku:
let i = 1: licznik zostaje utworzony i ustawiony na 1.- Sprawdzenie
i <= 3: prawda, więc wykonuje się ciało. Wypisuje1. - Wykonanie
i++:ima teraz wartość 2. - Sprawdzenie
i <= 3: prawda. Wypisuje2. - Wykonanie
i++:ima teraz wartość 3. - Sprawdzenie
i <= 3: prawda. Wypisuje3. - Wykonanie
i++:ima teraz wartość 4. - Sprawdzenie
i <= 3: fałsz. Koniec.
Krok aktualizacji wykonuje się po ciele pętli, a nie przed nim. Na tym ludzie się potykają.
Iteracja po tablicy przez indeks
Najczęstszym zadaniem pętli for jest przechodzenie po tablicy. Licznik służy jednocześnie jako indeks:
Kilka rzeczy wartych uwagi:
- Tablice są indeksowane od zera. Pierwszy element ma indeks
0, ostatnilength - 1. - Warunek to
i < fruits.length, a niei <= fruits.length. Użycie<=przeszłoby o jeden krok za koniec i wypisałoundefined. ijest zadeklarowane przezlet, więc jego zakresem jest pętla. Poza pętlą nie istnieje.
Jeśli potrzebujesz tylko wartości, a nie indeksu, for...of jest krótsze i czytelniejsze: omawiamy je na osobnej stronie.
break: wcześniejsze zakończenie
break natychmiast kończy pętlę. Przydaje się, gdy znajdziesz to, czego szukasz, i nie ma potrzeby iść dalej:
Gdy wykona się break, sterowanie przeskakuje za zamykający nawias klamrowy pętli. Krok aktualizacji się nie wykonuje, warunek nie jest ponownie sprawdzany: pętla po prostu się kończy.
continue: pominięcie tej iteracji
continue pomija resztę bieżącej iteracji i przechodzi od razu do kroku aktualizacji. Pętla działa dalej, tylko nie kończy bieżącego przebiegu.
Liczby parzyste trafiają na continue i pomijają console.log. Wypisywane są tylko nieparzyste. continue przydaje się, gdy chcesz odfiltrować niektóre iteracje bez zagnieżdżania reszty ciała pętli w if.
Kroki inne niż +1
Krok aktualizacji to po prostu wyrażenie. Nie musi to być i++. Liczenie co dwa:
Odliczanie w dół:
Przechodzenie po tablicy od końca, czasem przydatne, gdy usuwasz elementy w trakcie:
Cokolwiek wybierzesz, zasada jest ta sama: warunek i aktualizacja muszą ze sobą współgrać, żeby warunek w końcu stał się false. Jeśli nie współgrają, pętla działa w nieskończoność. for (let i = 0; i < 10; i--) to pętla nieskończona: i zmienia się w złą stronę.
Zagnieżdżone pętle for
Możesz umieścić jedną pętlę for w drugiej. Wewnętrzna pętla wykonuje się do końca dla każdej iteracji pętli zewnętrznej.
Dziewięć linii wyjścia: trzy iteracje zewnętrzne, po trzy wewnętrzne w każdej. Nadaj każdemu licznikowi sensowną nazwę (row/col, i/j) zamiast używać ponownie tej samej zmiennej.
Na jedno trzeba uważać: break i continue działają tylko na najbardziej wewnętrzną pętlę. Wyjście z pętli wewnętrznej nie zatrzymuje zewnętrznej. Jeśli tego potrzebujesz, ustaw flagę i sprawdzaj ją w pętli zewnętrznej albo wydziel zagnieżdżoną pracę do funkcji i wyjdź z niej przez return.
Typowe pułapki
Kilka rzeczy, które gryzą początkujących:
Błędy o jeden (off-by-one). i <= arr.length iteruje o jeden krok za daleko, i < arr.length - 1 zatrzymuje się o jeden krok za wcześnie. Standardowa forma to i < arr.length.
Zapomniana aktualizacja. Jeśli pominiesz i++ (albo jego odpowiednik), licznik nigdy się nie zmienia i pętla działa w nieskończoność:
for (let i = 0; i < 10; ) {
console.log(i); // never ends
}
Użycie var dla licznika. var ma zasięg funkcji, więc licznik wycieka poza pętlę i może powodować niespodzianki w domknięciach. Trzymaj się let.
Modyfikowanie tablicy w trakcie iteracji. Usuwanie elementów przesuwa indeksy i pominiesz niektóre elementy. Jeśli musisz usuwać elementy, iteruj od końca albo zbuduj nową tablicę przez filter.
Kiedy sięgnąć po coś innego
Klasyczna pętla for jest zawsze dostępna, ale JavaScript ma krótsze opcje dla typowych przypadków:
- Iteracja po wartościach tablicy:
for (const item of array)jest czytelniejsze. - Przekształcanie tablicy:
array.map(fn)zwraca nową tablicę. - Filtrowanie:
array.filter(fn). - Sumowanie lub redukcja:
array.reduce(fn, start). - Zrobienie czegoś dla każdego elementu:
array.forEach(fn).
Po klasyczne for sięgaj wtedy, gdy naprawdę potrzebujesz indeksu, musisz coś pominąć lub przerwać w połowie albo potrzebujesz niestandardowych kroków, np. odliczania w dół lub liczenia co dwa.
Dalej: pętle while
Pętla for błyszczy, gdy znasz zakres z góry. Gdy go nie znasz, czyli chcesz kontynuować, dopóki nie zmieni się jakiś warunek, lepiej pasują while i do...while. O nich jest następna strona.
Najczęściej zadawane pytania
Jaka jest składnia pętli for w JavaScript?
Trzy części oddzielone średnikami w nawiasach okrągłych: for (init; condition; update) { ... }. Inicjalizacja wykonuje się raz, warunek jest sprawdzany przed każdą iteracją, a aktualizacja wykonuje się po każdej iteracji. Typowa pętla wygląda tak: for (let i = 0; i < 10; i++) { ... }.
Jak przejść pętlą po tablicy w JavaScript?
Sprawdzi się klasyczna pętla for z indeksem: for (let i = 0; i < arr.length; i++) { console.log(arr[i]); }. Jeśli nie potrzebujesz indeksu, for...of jest czytelniejsze: for (const item of arr) { ... }. Do przekształcania i filtrowania zwykle lepiej nadają się metody tablic, takie jak map i filter.
Jak działają break i continue w pętli for?
break natychmiast kończy pętlę: wykonanie przeskakuje do kodu za pętlą. continue pomija resztę bieżącej iteracji i przechodzi od razu do kroku aktualizacji, a potem ponownie sprawdza warunek. Oba działają tylko na najbardziej wewnętrzną pętlę, chyba że użyjesz etykiet.
Dlaczego moja pętla for działa w nieskończoność?
Zwykle krok aktualizacji nigdy nie przybliża warunku do false. for (let i = 0; i < 10; i--) odlicza w dół bez końca, bo i zaczyna od 0 i staje się tylko coraz bardziej ujemne. Sprawdź dokładnie warunek i aktualizację: muszą ze sobą współgrać, żeby warunek w końcu stał się fałszywy.