• Aplikacje webowe
  • Pętla for w JavaScript - składnia, przykłady i typowe błędy

Pętla for w JavaScript - składnia, przykłady i typowe błędy

Radosław Krajewski 17 lipca 2026
Pętla for w JS: definicja zmiennej, warunek i modyfikacja wartości. Kod wyświetla liczby od 5 do 29.

Spis treści

Gdy aplikacja webowa ma przejść po tablicy produktów, wygenerować elementy listy albo wykonać operację określoną liczbę razy, najczęściej potrzebujesz pętli for. Pokażę jej składnię, praktyczne zastosowania w JavaScript, różnice między for, for...of i for...in, a także błędy, przez które kod potrafi działać o jedną iterację za dużo albo zatrzymać interfejs.

Najważniejsze zasady używania pętli for w JavaScript

  • Trzy elementy składni to inicjalizacja, warunek oraz zmiana wartości sterującej.
  • Indeks tablicy najczęściej zaczyna się od zera, dlatego warunek powinien używać operatora <.
  • for...of upraszcza przechodzenie po wartościach tablic, a for...in służy głównie do właściwości obiektów.
  • break kończy pętlę, natomiast continue pomija bieżącą iterację.
  • Przy dużej liczbie operacji synchroniczna pętla może zablokować interfejs użytkownika.

Jak działa klasyczna pętla for

Klasyczna konstrukcja for powtarza blok kodu tak długo, jak długo określony warunek zwraca wartość prawdziwą. Jej podstawowy zapis wygląda tak:

for (inicjalizacja; warunek; zmiana) {
  // kod wykonywany w każdej iteracji
}

Najczęściej inicjalizuję licznik, sprawdzam go w warunku i zwiększam o jeden po każdej iteracji. W tym przykładzie kod wykona się dokładnie pięć razy, dla wartości od 0 do 4:

for (let i = 0; i < 5; i++) {
  console.log(i);
}

Przebieg jest prosty. Najpierw wykonuje się let i = 0, potem JavaScript sprawdza i < 5, uruchamia blok kodu i na końcu wykonuje i++. Dopiero wtedy rozpoczyna się kolejna iteracja.

W praktyce najczęściej korzystam z let, ponieważ licznik zmienia swoją wartość. Deklaracja var działa w starszym stylu, ale ma szerszy zakres widoczności i może prowadzić do trudniejszych do wykrycia błędów. Przy współczesnym JavaScript wybór let dla zmiennego licznika jest po prostu bezpieczniejszy.

Iterowanie po elementach tablicy

Klasyczna pętla dobrze sprawdza się wtedy, gdy potrzebujesz indeksu. Jest to częsty przypadek podczas pracy z elementami DOM, gdy chcesz znaleźć konkretny element tablicy i zmienić jego zawartość:

const produkty = ["Laptop", "Monitor", "Klawiatura"];

for (let i = 0; i < produkty.length; i++) {
  console.log(`${i + 1}. ${produkty[i]}`);
}

Właściwość length zwraca liczbę elementów tablicy. Dzięki warunkowi i < produkty.length ostatni dostępny indeks pozostaje poprawny. Zapis i <= produkty.length byłby błędny, ponieważ próbowałby odczytać element o indeksie równym długości tablicy, a taki element nie istnieje.

Odliczanie w dół

Pętla nie musi zwiększać licznika. Gdy chcę przejść po tablicy od końca albo wyświetlić odliczanie, zmniejszam wartość sterującą:

for (let i = 5; i >= 1; i--) {
  console.log(i);
}

Trzeba tylko dopasować wszystkie trzy części konstrukcji. Jeśli licznik maleje, warunek musi sprawdzać, czy nadal jest większy lub równy wartości granicznej. Pominięcie tej zależności często prowadzi do pętli nieskończonej.

Pętla for w aplikacji webowej

W aplikacjach przeglądarkowych pętla służy nie tylko do wypisywania liczb w konsoli. Możesz użyć jej do tworzenia elementów interfejsu, filtrowania danych, aktualizowania klas CSS albo przygotowania fragmentu raportu.

Generowanie listy w DOM

Załóżmy, że masz tablicę nazw i chcesz wyświetlić je w elemencie ul. Pętla przechodzi po danych, tworzy element li i dodaje go do dokumentu:

const technologie = ["JavaScript", "Azure", " .NET"];
const lista = document.querySelector("#technologie");

for (let i = 0; i < technologie.length; i++) {
  const element = document.createElement("li");
  element.textContent = technologie[i];
  lista.appendChild(element);
}

Ten sposób jest czytelny, gdy każda iteracja wymaga kilku operacji. Użycie textContent zamiast innerHTML ogranicza ryzyko przypadkowego wstrzyknięcia kodu HTML pochodzącego z danych użytkownika. W prostych widokach różnica wydajności zwykle nie ma znaczenia, ale bezpieczne wstawianie tekstu ma znaczenie zawsze.

Praca z formularzem

Pętla może pomóc sprawdzić kilka pól formularza i zaznaczyć te, które są puste:

const pola = document.querySelectorAll("input[required]");

for (let i = 0; i < pola.length; i++) {
  if (pola[i].value.trim() === "") {
    pola[i].classList.add("blad");
  }
}

querySelectorAll zwraca kolekcję elementów, po której można iterować podobnie jak po tablicy. W nowszym kodzie często wybieram tu for...of, bo nie potrzebuję indeksu, ale klasyczny wariant nadal bywa przydatny, gdy komunikat błędu ma wskazywać numer pola.

Zagnieżdżone pętle

Dwie pętle pozwalają przejść po danych o strukturze tabeli, na przykład po wierszach i kolumnach. Trzeba jednak zachować umiar, ponieważ koszt wykonania rośnie wraz z liczbą elementów:

const tabela = [
  [1, 2, 3],
  [4, 5, 6]
];

for (let wiersz = 0; wiersz < tabela.length; wiersz++) {
  for (let kolumna = 0; kolumna < tabela[wiersz].length; kolumna++) {
    console.log(tabela[wiersz][kolumna]);
  }
}

Przy dwóch wymiarach łatwo przeoczyć, że każda iteracja zewnętrzna uruchamia całą pętlę wewnętrzną. Dla tablicy o rozmiarze 1000 na 1000 oznacza to nawet milion odwołań. Taka konstrukcja jest poprawna, ale przy dużych danych trzeba sprawdzić, czy nie da się ograniczyć liczby operacji.

for, for...of i for...in w praktycznym porównaniu

JavaScript oferuje kilka rodzajów pętli. Nie traktuję ich jako całkowicie wymiennych, ponieważ każda odpowiada innemu problemowi. Najlepsza konstrukcja to ta, która jasno pokazuje, czy pracujesz z indeksem, wartością, czy właściwością obiektu.

Konstrukcja Najlepsze zastosowanie Ważna cecha
for Tablice, indeksy, precyzyjna kontrola iteracji Możesz samodzielnie sterować początkiem, warunkiem i krokiem
for...of Wartości tablic, napisów, zbiorów i innych obiektów iterowalnych Kod jest krótszy, a indeks nie jest potrzebny
for...in Właściwości obiektów Zwraca nazwy kluczy, nie bezpośrednio ich wartości
forEach Proste operacje na każdym elemencie tablicy Nie pozwala wygodnie przerwać iteracji przez break

for...of dla wartości

Gdy nie potrzebuję numeru indeksu, wybieram zwykle for...of. Każda iteracja udostępnia bezpośrednio wartość elementu:

const ceny = [19, 29, 49];

for (const cena of ceny) {
  console.log(`Cena: ${cena} zł`);
}

Ten zapis ogranicza liczbę technicznych szczegółów i zmniejsza ryzyko pomyłki z indeksami. Działa także dla napisów, obiektów Set i Map, choć w przypadku Map otrzymasz pary klucz-wartość.

for...in dla obiektów

for...in przechodzi po nazwach właściwości obiektu. Wartość odczytasz dopiero za pomocą nawiasów kwadratowych:

const użytkownik = {
  imię: "Anna",
  rola: "developer",
  aktywny: true
};

for (const klucz in użytkownik) {
  console.log(`${klucz}: ${użytkownik[klucz]}`);
}

Nie używam for...in do zwykłych tablic, ponieważ może przechodzić także po odziedziczonych właściwościach. Do tablic lepsze są for, for...of albo metody takie jak map i filter. To drobna decyzja, która później poprawia czytelność kodu.

break, continue i warunki zakończenia

Sama składnia pętli nie wystarcza, gdy chcesz zakończyć wyszukiwanie po znalezieniu wyniku albo pominąć niepasujące dane. Do tego służą break i continue.

Przerwanie pętli przez break

break natychmiast kończy wykonywanie pętli. Jest dobrym rozwiązaniem, gdy szukasz jednego elementu i nie ma sensu analizować pozostałych:

const identyfikatory = [12, 18, 24, 31];
let znaleziony = null;

for (let i = 0; i < identyfikatory.length; i++) {
  if (identyfikatory[i] > 20) {
    znaleziony = identyfikatory[i];
    break;
  }
}

console.log(znaleziony);

Bez break kod sprawdziłby również kolejne elementy, chociaż pierwszy pasujący wynik już wystarcza. Przy dużych kolekcjach takie wcześniejsze zakończenie może ograniczyć liczbę operacji, ale nie powinno zastępować lepszego algorytmu, gdy problem jest bardziej złożony.

Pomijanie iteracji przez continue

continue pomija resztę bieżącej iteracji i przechodzi do następnej. W tym przykładzie wartości ujemne nie są przetwarzane:

const liczby = [4, -2, 8, -1, 10];

for (const liczba of liczby) {
  if (liczba < 0) {
    continue;
  }

  console.log(`Przetwarzam ${liczba}`);
}

Stosuję ten zapis wtedy, gdy warunek wykluczenia jest krótki i oczywisty. Jeśli takich wyjątków pojawia się kilka, pętla może stać się trudniejsza do śledzenia. Wtedy lepiej wcześniej odfiltrować dane albo wydzielić walidację do osobnej funkcji.

Najczęstsze błędy w pętli for

Najwięcej problemów nie wynika ze skomplikowanej składni, tylko z drobnych rozbieżności między warunkiem a zmianą licznika. Dobrze jest rozpoznawać je od razu, zanim pętla zacznie wpływać na interfejs albo dane użytkownika.

Pomyłka o jedną iterację

Najczęstszy błąd

to użycie <= zamiast < przy przechodzeniu po tablicy:

const elementy = ["A", "B", "C"];

for (let i = 0; i <= elementy.length; i++) {
  console.log(elementy[i]);
}

Ostatnia iteracja wypisze undefined, ponieważ poprawne indeksy to 0, 1 i 2, a elementy.length wynosi 3. Właśnie dlatego przy tablicach standardowy wzorzec i < tablica.length jest bezpieczniejszy.

Brak zmiany licznika

Jeśli warunek pozostaje prawdziwy, a licznik się nie zmienia, pętla nigdy się nie skończy:

let i = 0;

while (i < 3) {
  console.log(i);
  // brak i++
}

W klasycznej konstrukcji for zmiana licznika jest widoczna w jednym miejscu, dlatego łatwiej ją skontrolować. Przy bardziej niestandardowych pętlach zawsze sprawdzam, czy każda ścieżka wykonania prowadzi ostatecznie do zmiany wartości użytej w warunku.

Zmiana tablicy podczas iteracji

Usuwanie elementów z tablicy w trakcie przechodzenia po niej może sprawić, że kolejny element zostanie pominięty. Indeksy przesuwają się wtedy w trakcie działania pętli:

const liczby = [1, 2, 3, 4, 5];

for (let i = 0; i < liczby.length; i++) {
  if (liczby[i] % 2 === 0) {
    liczby.splice(i, 1);
    i--;
  }
}

Zmniejszenie indeksu po usunięciu elementu naprawia ten konkretny przypadek, ale kod staje się mniej oczywisty. Często czytelniej utworzyć nową tablicę za pomocą filter. Modyfikowanie kolekcji w miejscu ma sens, gdy zależy Ci na ograniczeniu alokacji pamięci i dobrze kontrolujesz wszystkie skutki uboczne.

Wydajność i asynchroniczność w JavaScript

Pętla wykonuje się synchronicznie, czyli kod po niej nie ruszy, dopóki wszystkie iteracje się nie zakończą. Dla kilkuset elementów zwykle nie ma to znaczenia, ale kosztowne obliczenia na dużych danych mogą zablokować główny wątek przeglądarki i sprawić, że przyciski przestaną reagować.

Nie zakładam automatycznie, że każda pętla jest problemem wydajnościowym. Najpierw mierzę działanie aplikacji, a dopiero później optymalizuję. Pomaga ograniczenie liczby operacji DOM, przetwarzanie danych poza widokiem i podział dużego zadania na mniejsze porcje.

Przeczytaj również: Nagłówek H2 w HTML - jak budować dobrą hierarchię?

Pętla i operacje asynchroniczne

Częstą pułapką jest użycie forEach z funkcją asynchroniczną:

users.forEach(async (user) => {
  await pobierzDane(user);
});

console.log("Gotowe");

Napis Gotowe może pojawić się przed zakończeniem wszystkich operacji, ponieważ forEach nie czeka na obietnice zwracane przez funkcję callback. Gdy wywołania mają być wykonywane po kolei, lepiej użyć for...of z await:

for (const user of users) {
  await pobierzDane(user);
}

console.log("Gotowe");

To rozwiązanie jest czytelne, ale wykonuje zadania sekwencyjnie. Jeśli operacje są niezależne, szybsze może być uruchomienie ich równolegle przez Promise.all. Wybór zależy od tego, czy kolejność ma znaczenie oraz czy serwer poradzi sobie z większą liczbą żądań jednocześnie.

Jak wybrać właściwy wariant w codziennym kodzie

Moja praktyczna zasada jest prosta. Sięgam po klasyczne for, gdy potrzebuję indeksu, pomijam elementy według pozycji albo chcę mieć pełną kontrolę nad warunkiem zakończenia. Gdy interesują mnie same wartości, zaczynam od for...of, bo szybciej pokazuje intencję kodu.

  • Wybierz for, gdy potrzebujesz indeksu, niestandardowego kroku lub wcześniejszego zakończenia.
  • Wybierz for...of, gdy przetwarzasz wartości tablicy, napisu, zbioru albo mapy.
  • Wybierz for...in, gdy analizujesz klucze zwykłego obiektu.
  • Wybierz map, gdy chcesz utworzyć nową tablicę na podstawie istniejącej.
  • Wybierz filter, gdy chcesz pozostawić tylko elementy spełniające warunek.
  • Wybierz find, gdy potrzebujesz pierwszego pasującego elementu zamiast ręcznie używać break.

Nie ma nagrody za użycie najbardziej rozbudowanej konstrukcji. W aplikacjach webowych największą różnicę robi kod, w którym od razu widać, po czym iterujesz i kiedy kończysz. Jeśli klasyczna pętla jest najczytelniejsza, nadal jest bardzo dobrym wyborem.

Mała kontrola przed uruchomieniem pętli

Przed wysłaniem kodu do przeglądarki sprawdzam cztery rzeczy: wartość początkową licznika, warunek, kierunek zmiany oraz dostęp do elementu tablicy. Ten krótki przegląd wychwytuje większość błędów bez uruchamiania debuggera.

Dobrze napisana pętla for jest przewidywalna, ma jasno określony koniec i nie wykonuje niepotrzebnych operacji. W prostym widoku może przejść po kilku elementach DOM, a w bardziej rozbudowanej aplikacji obsłużyć dane z API, formularza lub modelu widoku. Najważniejsze pozostaje dopasowanie rodzaju pętli do zadania, zamiast mechanicznego używania jednego wzorca wszędzie.

FAQ - Najczęstsze pytania

Zainicjalizuj licznik od 0, użyj warunku i < tablica.length i zwiększaj go przez i++. Operator <= może spowodować dodatkową iterację i odczyt wartości undefined.

Klasyczne for zapewnia kontrolę nad indeksem, warunkiem i krokiem. for...of służy do przechodzenia po wartościach tablic, napisów, zbiorów i map, a for...in do nazw właściwości obiektów, dlatego nie jest zalecane do zwykłych tablic.

W każdej iteracji utwórz element przez document.createElement, ustaw jego tekst za pomocą textContent i dodaj go przez appendChild. textContent ogranicza ryzyko wstrzyknięcia kodu HTML pochodzącego z danych użytkownika.

forEach nie oczekuje na obietnice zwracane przez funkcję async, więc kod po pętli może wykonać się zbyt wcześnie. Do operacji sekwencyjnych użyj for...of z await, a niezależne zadania możesz uruchomić równolegle przez Promise.all.

Oceń artykuł

Ocena: 0.00 Liczba głosów: 0

Tagi

javascript
pętle
dom
tablice
asynchroniczność
Autor Radosław Krajewski
Radosław Krajewski
Nazywam się Radosław Krajewski i od 6 lat zgłębiam tajniki programowania .NET, chmury Azure oraz sztucznej inteligencji. Moja przygoda z tymi technologiami zaczęła się od fascynacji tym, jak złożone problemy można rozwiązywać za pomocą kodu i innowacyjnych narzędzi. Staram się przekazywać tę wiedzę w sposób zrozumiały, dzieląc się swoimi doświadczeniami i spostrzeżeniami na kursdotnet.pl. W moich artykułach skupiam się na praktycznych aspektach, porównuję różne rozwiązania i analizuję najnowsze trendy, aby dostarczyć Wam rzetelne i aktualne informacje, które pomogą Wam rozwijać się w tej dynamicznie zmieniającej się dziedzinie.

Udostępnij artykuł

Napisz komentarz