W Parku Jurajskim rutynowe zadania muszą być wykonywane regularnie i powtarzalnie: sprawdzanie ogrodzenia każdego wybiegu co godzinę, monitorowanie wszystkich kamer bezpieczeństwa, aktualizacja statusu zdrowia każdego dinozaura. Ręczne wykonywanie tych czynności byłoby żmudne i podatne na błędy.
Podobnie w JavaScript, pętle pozwalają na automatyczne i efektywne wykonywanie powtarzalnych operacji. Zamiast pisać ten sam kod wielokrotnie, możemy użyć pętli do wykonania go dla wielu elementów lub określoną liczbę razy.
Pętla
for jest jedną z najpopularniejszych pętli w JavaScript. Składa się z trzech części: inicjalizacji, warunku i wyrażenia aktualizującego.1// Podstawowa struktura pętli for
2for (inicjalizacja; warunek; aktualizacja) {
3 // Blok kodu do wykonania
4}W praktyce w Parku Jurajskim, możemy użyć pętli
for do automatyzacji rutynowych zadań:1// Sprawdzanie stanu zdrowia każdego dinozaura w sektorze
2let dinozaury = ["Tyranozaur", "Velociraptor", "Triceratops", "Stegozaur", "Brachiozaur"];
3
4for (let i = 0; i < dinozaury.length; i++) {
5 console.log(`Sprawdzanie stanu zdrowia: ${dinozaury[i]}`);
6 // Kod sprawdzający stan zdrowia konkretnego dinozaura...
7}
8
9// Wynik:
10// Sprawdzanie stanu zdrowia: Tyranozaur
11// Sprawdzanie stanu zdrowia: Velociraptor
12// Sprawdzanie stanu zdrowia: Triceratops
13// Sprawdzanie stanu zdrowia: Stegozaur
14// Sprawdzanie stanu zdrowia: Brachiozaur
15
16// Monitoring kamer bezpieczeństwa
17for (let kamera = 1; kamera <= 10; kamera++) {
18 console.log(`Sprawdzanie kamery #${kamera}`);
19 // Kod analizujący obraz z kamery...
20}
21
22// Generowanie raportu dziennego za ostatnie 7 dni
23for (let dzień = 1; dzień <= 7; dzień++) {
24 console.log(`Generowanie raportu za dzień #${dzień}`);
25 // Kod generujący raport za konkretny dzień...
26}Pętla
for ma trzy główne elementy:let i = 0) - wykonywana raz, przed rozpoczęciem pętlii < dinozaury.length) - sprawdzany przed każdą iteracją; pętla kończy się, gdy warunek zwraca falsei++) - wykonywana po każdej iteracjiPętla
for...of to nowsza i bardziej elegancka forma pętli, która pozwala na iterację po elementach kolekcji (tablice, stringi, mapy, sety, itp.) bez potrzeby śledzenia indeksów.1// Struktura pętli for...of
2for (let element of kolekcja) {
3 // Blok kodu do wykonania dla każdego elementu
4}Pętla
for...of jest szczególnie przydatna, gdy interesują nas same elementy, a nie ich indeksy:1// Sprawdzanie stanu zdrowia każdego dinozaura przy użyciu for...of
2let dinozaury = ["Tyranozaur", "Velociraptor", "Triceratops", "Stegozaur", "Brachiozaur"];
3
4for (let dinozaur of dinozaury) {
5 console.log(`Sprawdzanie stanu zdrowia: ${dinozaur}`);
6 // Kod sprawdzający stan zdrowia konkretnego dinozaura...
7}
8
9// Sprawdzanie poziomu zapasów różnych rodzajów pokarmu
10let zapasyPokarmu = {
11 mięso: 500, // kg
12 liście: 1200, // kg
13 owoce: 300, // kg
14 ryby: 200 // kg
15};
16
17// Uwaga: for...of nie działa bezpośrednio na obiektach, ale możemy użyć Object.entries()
18for (let [rodzajPokarmu, ilość] of Object.entries(zapasyPokarmu)) {
19 console.log(`Pokarm: ${rodzajPokarmu}, Ilość: ${ilość} kg`);
20
21 if (ilość < 300) {
22 console.log(`UWAGA: Niski poziom zapasów ${rodzajPokarmu}! Należy uzupełnić.`);
23 }
24}
25
26// Wynik:
27// Pokarm: mięso, Ilość: 500 kg
28// Pokarm: liście, Ilość: 1200 kg
29// Pokarm: owoce, Ilość: 300 kg
30// Pokarm: ryby, Ilość: 200 kg
31// UWAGA: Niski poziom zapasów ryby! Należy uzupełnić.Pętla
for...in jest przeznaczona do iteracji po właściwościach obiektu. Zwraca nazwy kluczy (właściwości) obiektu.1// Struktura pętli for...in
2for (let klucz in obiekt) {
3 // Blok kodu do wykonania dla każdego klucza
4}Przykład użycia w Parku Jurajskim:
1// Analiza danych o dinozaurze
2let tyranozaur = {
3 gatunek: "Tyrannosaurus Rex",
4 wiek: 12,
5 waga: 8000, // kg
6 długość: 12, // m
7 wysokość: 5.6, // m
8 prędkość: 27, // km/h
9 poziomAgresji: "Bardzo wysoki"
10};
11
12// Wypisanie wszystkich informacji o dinozaurze
13for (let cecha in tyranozaur) {
14 console.log(`${cecha}: ${tyranozaur[cecha]}`);
15}
16
17// Sprawdzenie, które cechy dinozaura przekraczają wartości bezpieczeństwa
18let limityBezpieczeństwa = {
19 waga: 5000, // kg
20 prędkość: 25, // km/h
21 poziomAgresji: "Wysoki"
22};
23
24for (let parametr in limityBezpieczeństwa) {
25 if (tyranozaur[parametr] > limityBezpieczeństwa[parametr] ||
26 (parametr === "poziomAgresji" && tyranozaur[parametr] === "Bardzo wysoki")) {
27 console.log(`UWAGA: Parametr ${parametr} przekracza wartości bezpieczeństwa!`);
28 }
29}
30
31// Wynik:
32// UWAGA: Parametr waga przekracza wartości bezpieczeństwa!
33// UWAGA: Parametr prędkość przekracza wartości bezpieczeństwa!
34// UWAGA: Parametr poziomAgresji przekracza wartości bezpieczeństwa!Ważna uwaga: Pętla
for...in iteruje po wszystkich właściwościach obiektu, w tym dziedziczonych. Jeśli chcemy ograniczyć się tylko do własnych właściwości obiektu, możemy użyć metody hasOwnProperty():1for (let cecha in tyranozaur) {
2 if (tyranozaur.hasOwnProperty(cecha)) {
3 console.log(`${cecha}: ${tyranozaur[cecha]}`);
4 }
5}Ważne jest, aby zrozumieć różnicę między tymi dwoma typami pętli:
1let dinosaurNames = ["T-Rex", "Raptor", "Triceratops"];
2
3// for...of (wartości)
4for (let name of dinosaurNames) {
5 console.log(name); // "T-Rex", "Raptor", "Triceratops"
6}
7
8// for...in (indeksy/klucze)
9for (let index in dinosaurNames) {
10 console.log(index); // "0", "1", "2"
11 console.log(dinosaurNames[index]); // "T-Rex", "Raptor", "Triceratops"
12}Pętla
while wykonuje blok kodu, dopóki określony warunek jest prawdziwy. W przeciwieństwie do pętli for, pętla while ma tylko warunek.1// Struktura pętli while
2while (warunek) {
3 // Blok kodu do wykonania
4}W Parku Jurajskim, pętla
while może być używana do procesów, które nie mają z góry określonej liczby iteracji:1// System monitorowania temperatury inkubatora jaj
2let temperatura = 37.5; // stopnie Celsjusza
3let docelowaTemperatura = 38.2;
4let przyrostTemperatury = 0.1;
5
6console.log("Rozpoczęcie procesu podgrzewania inkubatora...");
7
8while (temperatura < docelowaTemperatura) {
9 console.log(`Aktualna temperatura: ${temperatura.toFixed(1)}°C`);
10 temperatura += przyrostTemperatury;
11 // Kod do symulacji upływu czasu...
12}
13
14console.log(`Osiągnięto docelową temperaturę: ${temperatura.toFixed(1)}°C`);
15
16// System monitorowania poziomu zasilania
17let poziomZasilania = 100; // procent
18let krytycznyPoziom = 20;
19let spadekZasilania = 5;
20
21console.log("Monitorowanie poziomu zasilania po awarii głównego generatora...");
22
23while (poziomZasilania > krytycznyPoziom) {
24 console.log(`Poziom zasilania: ${poziomZasilania}%`);
25 poziomZasilania -= spadekZasilania;
26 // Kod do symulacji upływu czasu...
27}
28
29console.log(`ALARM! Krytyczny poziom zasilania: ${poziomZasilania}%`);
30console.log("Uruchamianie protokołu awaryjnego...");Pętla
do...while jest podobna do pętli while, ale z jedną kluczową różnicą: blok kodu jest zawsze wykonywany przynajmniej raz, zanim warunek zostanie sprawdzony.1// Struktura pętli do...while
2do {
3 // Blok kodu do wykonania
4} while (warunek);Ta pętla jest przydatna, gdy chcemy, aby kod został wykonany co najmniej raz, niezależnie od warunku:
1// Procedura uruchamiania systemu bezpieczeństwa
2let systemSprawny = false;
3let liczbaProb = 0;
4let maksymalnaLiczbaProb = 3;
5
6do {
7 console.log("Próba uruchomienia systemu bezpieczeństwa...");
8 liczbaProb++;
9
10 // Symulacja losowości działania systemu
11 systemSprawny = Math.random() > 0.5; // 50% szans na sukces
12
13 if (systemSprawny) {
14 console.log("System bezpieczeństwa uruchomiony pomyślnie!");
15 } else {
16 console.log(`Uruchomienie systemu nie powiodło się. Próba ${liczbaProb} z ${maksymalnaLiczbaProb}.`);
17 }
18
19} while (!systemSprawny && liczbaProb < maksymalnaLiczbaProb);
20
21if (!systemSprawny) {
22 console.log("KRYTYCZNY BŁĄD: System bezpieczeństwa nie może zostać uruchomiony. Konieczna interwencja techniczna!");
23}
24
25// Procedura ewakuacji
26let pozostaliLudzie = 100;
27
28do {
29 console.log(`Pozostało ${pozostaliLudzie} osób do ewakuacji.`);
30 // Symulacja ewakuacji - każda iteracja to jedna grupa ewakuowanych
31 let wielkośćGrupy = Math.floor(Math.random() * 20) + 10; // 10-29 osób
32 pozostaliLudzie -= wielkośćGrupy;
33
34 // Upewniamy się, że nie otrzymamy ujemnej liczby
35 if (pozostaliLudzie < 0) pozostaliLudzie = 0;
36
37 console.log(`Ewakuowano grupę ${wielkośćGrupy} osób.`);
38
39} while (pozostaliLudzie > 0);
40
41console.log("Wszyscy zostali ewakuowani. Obiekt jest pusty.");JavaScript oferuje dwie specjalne instrukcje do kontrolowania przebiegu pętli:
1// Poszukiwanie uszkodzonej sekcji ogrodzenia
2let sekcjeOgrodzenia = [
3 { id: 1, status: "sprawna" },
4 { id: 2, status: "sprawna" },
5 { id: 3, status: "uszkodzona" },
6 { id: 4, status: "sprawna" },
7 { id: 5, status: "sprawna" }
8];
9
10let znalezionoUszkodzenie = false;
11
12for (let i = 0; i < sekcjeOgrodzenia.length; i++) {
13 console.log(`Sprawdzanie sekcji #${sekcjeOgrodzenia[i].id}...`);
14
15 if (sekcjeOgrodzenia[i].status === "uszkodzona") {
16 console.log(`UWAGA! Znaleziono uszkodzoną sekcję #${sekcjeOgrodzenia[i].id}!`);
17 console.log("Wysyłanie zespołu naprawczego...");
18 znalezionoUszkodzenie = true;
19 break; // Przerywamy pętlę, gdy znaleźliśmy uszkodzenie
20 }
21}
22
23if (!znalezionoUszkodzenie) {
24 console.log("Wszystkie sekcje ogrodzenia są sprawne.");
25}
26
27// Wynik:
28// Sprawdzanie sekcji #1...
29// Sprawdzanie sekcji #2...
30// Sprawdzanie sekcji #3...
31// UWAGA! Znaleziono uszkodzoną sekcję #3!
32// Wysyłanie zespołu naprawczego...1// Sprawdzanie stanu zdrowia dinozaurów, pomijając te, które są w trakcie badań
2let dinozaury = [
3 { nazwa: "Rex", gatunek: "Tyranozaur", dostępny: true },
4 { nazwa: "Blue", gatunek: "Velociraptor", dostępny: false }, // W trakcie badań
5 { nazwa: "Spike", gatunek: "Stegozaur", dostępny: true },
6 { nazwa: "Cera", gatunek: "Triceratops", dostępny: false }, // W trakcie badań
7 { nazwa: "Bronty", gatunek: "Brontozaur", dostępny: true }
8];
9
10console.log("Rozpoczęcie codziennych badań kontrolnych...");
11
12for (let i = 0; i < dinozaury.length; i++) {
13 if (!dinozaury[i].dostępny) {
14 console.log(`Dinozaur ${dinozaury[i].nazwa} (${dinozaury[i].gatunek}) jest już w trakcie badań. Pomijam.`);
15 continue; // Przechodzimy do następnej iteracji, pomijając resztę kodu w tej iteracji
16 }
17
18 console.log(`Przeprowadzanie badania dinozaura ${dinozaury[i].nazwa} (${dinozaury[i].gatunek})...`);
19 console.log("Badanie zakończone. Stan zdrowia: dobry.");
20}
21
22// Wynik:
23// Rozpoczęcie codziennych badań kontrolnych...
24// Przeprowadzanie badania dinozaura Rex (Tyranozaur)...
25// Badanie zakończone. Stan zdrowia: dobry.
26// Dinozaur Blue (Velociraptor) jest już w trakcie badań. Pomijam.
27// Przeprowadzanie badania dinozaura Spike (Stegozaur)...
28// Badanie zakończone. Stan zdrowia: dobry.
29// Dinozaur Cera (Triceratops) jest już w trakcie badań. Pomijam.
30// Przeprowadzanie badania dinozaura Bronty (Brontozaur)...
31// Badanie zakończone. Stan zdrowia: dobry.Pętle mogą być także zagnieżdżane jedna w drugiej, co jest przydatne przy pracy z danymi wielowymiarowymi:
1// Sprawdzanie stanu ogrodzeń we wszystkich sektorach Parku Jurajskiego
2
3// Tablica dwuwymiarowa: [sektor][sekcja_ogrodzenia]
4let statusOgrodzeń = [
5 // Sektor 1
6 [
7 { id: "1A", stan: "sprawne" },
8 { id: "1B", stan: "sprawne" },
9 { id: "1C", stan: "uszkodzone" }
10 ],
11 // Sektor 2
12 [
13 { id: "2A", stan: "sprawne" },
14 { id: "2B", stan: "sprawne" },
15 { id: "2C", stan: "sprawne" }
16 ],
17 // Sektor 3
18 [
19 { id: "3A", stan: "sprawne" },
20 { id: "3B", stan: "uszkodzone" },
21 { id: "3C", stan: "sprawne" }
22 ]
23];
24
25console.log("Rozpoczęcie inspekcji ogrodzeń we wszystkich sektorach...");
26
27for (let i = 0; i < statusOgrodzeń.length; i++) {
28 console.log(`
29Inspekcja sektora ${i + 1}:`);
30
31 let wszystkieSprawne = true;
32
33 for (let j = 0; j < statusOgrodzeń[i].length; j++) {
34 let sekcja = statusOgrodzeń[i][j];
35 console.log(` Sekcja ${sekcja.id}: ${sekcja.stan}`);
36
37 if (sekcja.stan === "uszkodzone") {
38 wszystkieSprawne = false;
39 console.log(` UWAGA: Sekcja ${sekcja.id} wymaga naprawy!`);
40 }
41 }
42
43 if (wszystkieSprawne) {
44 console.log(` Wszystkie ogrodzenia w sektorze ${i + 1} są sprawne.`);
45 } else {
46 console.log(` W sektorze ${i + 1} wykryto uszkodzone ogrodzenia.`);
47 }
48}
49
50// Wynik:
51// Rozpoczęcie inspekcji ogrodzeń we wszystkich sektorach...
52//
53// Inspekcja sektora 1:
54// Sekcja 1A: sprawne
55// Sekcja 1B: sprawne
56// Sekcja 1C: uszkodzone
57// UWAGA: Sekcja 1C wymaga naprawy!
58// W sektorze 1 wykryto uszkodzone ogrodzenia.
59//
60// Inspekcja sektora 2:
61// Sekcja 2A: sprawne
62// Sekcja 2B: sprawne
63// Sekcja 2C: sprawne
64// Wszystkie ogrodzenia w sektorze 2 są sprawne.
65//
66// Inspekcja sektora 3:
67// Sekcja 3A: sprawne
68// Sekcja 3B: uszkodzone
69// UWAGA: Sekcja 3B wymaga naprawy!
70// Sekcja 3C: sprawne
71// W sektorze 3 wykryto uszkodzone ogrodzenia.Pętla nieskończona to pętla, która nigdy się nie kończy, ponieważ jej warunek zakończenia nigdy nie jest spełniony. W Parku Jurajskim, pętla nieskończona w systemie bezpieczeństwa mogłaby prowadzić do katastrofy, podobnie jak w programowaniu może powodować zawieszenie aplikacji lub zużycie wszystkich zasobów.
Oto przykład pętli nieskończonej:
1// UWAGA: To jest pętla nieskończona! Nie uruchamiaj tego kodu!
2while (true) {
3 console.log("To się będzie wyświetlać w nieskończoność!");
4}
5
6// Inny przykład pętli nieskończonej:
7for (let i = 0; i >= 0; i++) {
8 console.log(i); // To będzie liczyć w nieskończoność!
9}Aby uniknąć pętli nieskończonych:
break jako zabezpieczenia1// Bezpieczniejsza wersja z limitem iteracji
2let maksymalnaLiczbaIteracji = 1000;
3let licznikIteracji = 0;
4
5// Przykład bezpiecznego monitorowania
6while (monitorujPark()) {
7 // Kod monitorowania parku...
8
9 licznikIteracji++;
10 if (licznikIteracji >= maksymalnaLiczbaIteracji) {
11 console.log("Osiągnięto maksymalną liczbę iteracji. Przerwanie pętli.");
12 break;
13 }
14}
15
16function monitorujPark() {
17 // Logika monitorowania...
18 return true; // Normalnie zwracałoby true lub false w zależności od warunków
19}1// Nieoptymalna pętla - długość tablicy jest przeliczana w każdej iteracji
2for (let i = 0; i < dinozaury.length; i++) {
3 // Kod...
4}
5
6// Zoptymalizowana pętla - długość tablicy jest przeliczana tylko raz
7for (let i = 0, len = dinozaury.length; i < len; i++) {
8 // Kod...
9}1// Wczesne wyjście z pętli po znalezieniu pierwszego pasującego elementu
2function znajdźDinozaura(nazwa) {
3 for (let dinozaur of bazaDinozaurów) {
4 if (dinozaur.nazwa === nazwa) {
5 return dinozaur; // Natychmiastowy zwrot po znalezieniu
6 }
7 }
8 return null; // Brak pasującego dinozaura
9}1// Niebezpieczne - modyfikowanie licznika wewnątrz pętli
2for (let i = 0; i < 10; i++) {
3 console.log(i);
4 if (i === 5) {
5 i = 8; // Przeskakujemy część iteracji - to może być mylące
6 }
7}
8
9// Lepsze podejście - użyj instrukcji continue lub break
10for (let i = 0; i < 10; i++) {
11 if (i > 5 && i < 9) {
12 continue; // Przeskakujemy iteracje 6, 7, 8
13 }
14 console.log(i);
15}Pętle w JavaScript, podobnie jak rutynowe procedury w Parku Jurajskim, pozwalają na efektywne wykonywanie powtarzalnych operacji:
Dodatkowo, instrukcje kontrolne:
Wybór odpowiedniej pętli zależy od konkretnego przypadku użycia, ale ogólnie należy dążyć do:
W następnej lekcji przyjrzymy się funkcjom, które pozwalają na organizowanie kodu w wielokrotnie używalne bloki - niezbędne dla utrzymania porządku w tak złożonym systemie jak Park Jurajski.