Usamos cookies para mejorar tu experiencia en el sitio
CodeWorlds

Instrukcje warunkowe (if, else, switch)

W Parku Jurajskim, systemy bezpieczeństwa i protokoły operacyjne muszą nieustannie podejmować decyzje: co zrobić, gdy poziom zasilania spadnie poniżej krytycznego poziomu? Jak zareagować, gdy T-Rex zbliży się do ogrodzenia? Jakie procedury uruchomić w przypadku różnych poziomów zagrożenia?

Podobnie, w JavaScript, instrukcje warunkowe pozwalają na podejmowanie decyzji w kodzie na podstawie określonych warunków. Przyjrzyjmy się trzem głównym typom instrukcji warunkowych: if, else if/else i switch.

Instrukcja if

Instrukcja

if
jest najprostszą formą podejmowania decyzji. Wykonuje blok kodu, jeśli określony warunek jest prawdziwy.

1// Podstawowa struktura instrukcji if
2if (warunek) {
3  // Kod do wykonania, gdy warunek jest prawdziwy
4}

W praktyce, w Parku Jurajskim, możemy użyć instrukcji

if
do sprawdzenia, czy należy uruchomić dodatkowe zabezpieczenia:

1// System monitorowania poziomu zasilania ogrodzenia
2let poziomZasilania = 75; // procent
3let poziomKrytyczny = 30; // procent
4
5if (poziomZasilania < poziomKrytyczny) {
6  console.log("UWAGA! Krytyczny poziom zasilania. Uruchomienie generatorów zapasowych.");
7  // Kod aktywujący zapasowe generatory...
8}
9
10// System monitorowania aktywności dinozaurów
11let odległośćTRexaOdOgrodzenia = 50; // metry
12let progBezpieczeństwa = 10; // metry
13
14if (odległośćTRexaOdOgrodzenia <= progBezpieczeństwa) {
15  console.log("ALERT! T-Rex zbliża się do ogrodzenia. Aktywacja dodatkowych zabezpieczeń.");
16  // Kod zwiększający napięcie w ogrodzeniu...
17}

Instrukcje if...else

Jeśli chcemy wykonać różne działania w zależności od tego, czy warunek jest prawdziwy czy fałszywy, używamy konstrukcji

if...else
.

1// Struktura if...else
2if (warunek) {
3  // Kod do wykonania, gdy warunek jest prawdziwy
4} else {
5  // Kod do wykonania, gdy warunek jest fałszywy
6}

W Parku Jurajskim, taka konstrukcja może być używana do decydowania o otwarciu lub zamknięciu atrakcji:

1// System podejmowania decyzji o dostępności atrakcji
2let pogodaOdpowiednia = true;
3let wskaźnikBezpieczeństwa = 3; // skala 1-5
4let minimalnyPoziomBezpieczeństwa = 4;
5
6if (pogodaOdpowiednia && wskaźnikBezpieczeństwa >= minimalnyPoziomBezpieczeństwa) {
7  console.log("Atrakcja 'Safari z Dinozaurami' jest otwarta dla zwiedzających.");
8  // Kod otwierający bramy, aktywujący kolejkę...
9} else {
10  console.log("Atrakcja 'Safari z Dinozaurami' jest tymczasowo zamknięta ze względów bezpieczeństwa.");
11  // Kod zamykający bramy, informujący personel...
12}

Instrukcje if...else if...else

Gdy mamy więcej niż dwie możliwe ścieżki działania, możemy użyć konstrukcji

if...else if...else
.

1// Struktura if...else if...else
2if (warunek1) {
3  // Kod do wykonania, gdy warunek1 jest prawdziwy
4} else if (warunek2) {
5  // Kod do wykonania, gdy warunek1 jest fałszywy, ale warunek2 jest prawdziwy
6} else {
7  // Kod do wykonania, gdy żaden z warunków nie jest prawdziwy
8}

W kontekście Parku Jurajskiego, taką konstrukcję można zastosować np. do systemu ostrzegania o różnych poziomach zagrożenia:

1// System ostrzegania o zagrożeniach
2let liczbaDrapieżnikówNaWolności = 0;
3let poziomUszkodzeniaOgrodzenia = 15; // procent
4
5if (liczbaDrapieżnikówNaWolności > 0) {
6  console.log("KOD CZERWONY! Ewakuacja natychmiastowa! Drapieżniki na wolności!");
7  // Kod uruchamiający alarmy, procedury ewakuacyjne...
8} else if (poziomUszkodzeniaOgrodzenia > 30) {
9  console.log("KOD POMARAŃCZOWY! Wysokie ryzyko ucieczki dinozaurów. Przygotować się do ewakuacji.");
10  // Kod przygotowujący park do potencjalnej ewakuacji...
11} else if (poziomUszkodzeniaOgrodzenia > 10) {
12  console.log("KOD ŻÓŁTY! Uszkodzenia ogrodzenia wykryte. Wysłać zespół naprawczy.");
13  // Kod wzywający zespół techniczny...
14} else {
15  console.log("KOD ZIELONY. Wszystkie systemy działają prawidłowo.");
16  // Normalny tryb operacyjny...
17}

Instrukcje if zagnieżdżone

Możemy również umieszczać instrukcje warunkowe wewnątrz innych instrukcji warunkowych. Takie zagnieżdżone instrukcje if są przydatne, gdy chcemy sprawdzić wiele warunków sekwencyjnie.

1// Przykład zagnieżdżonych instrukcji if
2let statusSystemu = "operacyjny";
3let poziomDostępu = "administrator";
4let kodBezpieczeństwa = "A123";
5
6if (statusSystemu === "operacyjny") {
7  console.log("System działa prawidłowo.");
8  
9  if (poziomDostępu === "administrator") {
10    console.log("Dostęp administratora przyznany.");
11    
12    if (kodBezpieczeństwa === "A123") {
13      console.log("Dostęp do protokołów bezpieczeństwa przyznany.");
14      // Kod ujawniający tajne protokoły bezpieczeństwa...
15    } else {
16      console.log("Błędny kod bezpieczeństwa.");
17    }
18  } else {
19    console.log("Brak uprawnień administratora.");
20  }
21} else {
22  console.log("System nie działa prawidłowo. Uruchom diagnostykę.");
23}

Chociaż zagnieżdżone instrukcje if są czasami konieczne, ich nadmierne użycie może prowadzić do tzw. "piramidy zagłady" (callback hell) lub "kodu drabinkowego", który jest trudny do czytania i utrzymania. W takich przypadkach warto rozważyć refaktoryzację kodu przy użyciu podejścia wczesnego zwrotu (early return) lub instrukcji switch.

Instrukcja switch

Instrukcja

switch
jest alternatywą dla wielu instrukcji
if...else if...else
, szczególnie gdy porównujemy jedną wartość z wieloma możliwymi wartościami.

1// Struktura instrukcji switch
2switch (wyrażenie) {
3  case wartość1:
4    // Kod do wykonania, gdy wyrażenie === wartość1
5    break;
6  case wartość2:
7    // Kod do wykonania, gdy wyrażenie === wartość2
8    break;
9  // ... więcej przypadków
10  default:
11    // Kod do wykonania, gdy żaden case nie pasuje
12}

W Parku Jurajskim, instrukcja

switch
może być używana np. do określania protokołów dla różnych gatunków dinozaurów:

1// System protokołów dla różnych gatunków
2let gatunekDinozaura = "Velociraptor";
3
4switch (gatunekDinozaura) {
5  case "Tyranozaur":
6    console.log("Protokół bezpieczeństwa T-REX-01: Maksymalny poziom zabezpieczeń.");
7    console.log("Wymagane podwójne ogrodzenie elektryczne, stały monitoring wideo.");
8    break;
9  case "Velociraptor":
10    console.log("Protokół bezpieczeństwa RAPTOR-02: Wysoki poziom zabezpieczeń.");
11    console.log("Wymagane wzmocnione ogrodzenie, monitoring aktywności w grupie.");
12    break;
13  case "Triceratops":
14    console.log("Protokół bezpieczeństwa HERB-03: Standardowy poziom zabezpieczeń.");
15    console.log("Wymagane podstawowe ogrodzenie, monitoring dobrostanu stada.");
16    break;
17  case "Brachiozaur":
18    console.log("Protokół bezpieczeństwa HERB-04: Niski poziom zabezpieczeń.");
19    console.log("Wymagane oznaczenie terenu, regularne dostawy pożywienia.");
20    break;
21  default:
22    console.log("Nieznany gatunek dinozaura. Zastosuj standardowy protokół bezpieczeństwa.");
23    console.log("Skontaktuj się z działem paleontologii w celu identyfikacji gatunku.");
24}

Instrukcja break w switch

Zauważ, że każdy przypadek

case
kończy się instrukcją
break
. Jest to niezwykle ważne, ponieważ bez
break
, wykonanie kodu będzie kontynuowane przez wszystkie kolejne przypadki, niezależnie od tego, czy pasują one do wyrażenia, czy nie. Ta właściwość nazywana jest "przenikaniem" (fall-through).

1// Przykład bez instrukcji break - "przenikanie"
2let poziomZagrożenia = 2; // skala 1-3
3
4switch (poziomZagrożenia) {
5  case 3:
6    console.log("Uruchom procedurę ewakuacji parku!");
7    // brak break - wykonanie przechodzi do następnego case
8  case 2:
9    console.log("Zamknij wszystkie atrakcje i zgromadź personel.");
10    // brak break - wykonanie przechodzi do następnego case
11  case 1:
12    console.log("Zwiększ częstotliwość monitorowania systemów bezpieczeństwa.");
13    // brak break - wykonanie przechodzi do default
14  default:
15    console.log("Utrzymuj standardowe procedury bezpieczeństwa.");
16}
17
18// Wynik dla poziomZagrożenia = 2:
19// "Zamknij wszystkie atrakcje i zgromadź personel."
20// "Zwiększ częstotliwość monitorowania systemów bezpieczeństwa."
21// "Utrzymuj standardowe procedury bezpieczeństwa."

Czasami "przenikanie" może być celowe i użyteczne, ale najczęściej jest wynikiem błędu. Zawsze upewnij się, że rozumiesz i zamierzasz takie zachowanie, jeśli rezygnujesz z instrukcji

break
.

Wiele przypadków z tym samym kodem

Jednym z prawomocnych zastosowań "przenikania" jest obsługa wielu przypadków z tym samym kodem:

1// Grupowanie przypadków
2let dzieńTygodnia = "sobota";
3
4switch (dzieńTygodnia) {
5  case "poniedziałek":
6  case "wtorek":
7  case "środa":
8  case "czwartek":
9  case "piątek":
10    console.log("Park Jurajski otwarty od 9:00 do 18:00.");
11    break;
12  case "sobota":
13  case "niedziela":
14    console.log("Park Jurajski otwarty od 8:00 do 20:00 (godziny weekendowe).");
15    break;
16  default:
17    console.log("Nieprawidłowy dzień tygodnia.");
18}

Wyrażenia warunkowe (ternary operator)

Dla prostych warunków, możemy użyć operatora warunkowego (nazywanego też operatorem trójskładnikowym lub ternary operator), który jest bardziej zwięzły niż instrukcja

if...else
.

1// Struktura operatora warunkowego
2warunek ? wyrażenieGdyPrawda : wyrażenieGdyFałsz

Przykład wykorzystania w Parku Jurajskim:

1// Przydzielanie poziomu dostępu
2let jestPracownikiem = true;
3let poziomDostępu = jestPracownikiem ? "Pełny dostęp" : "Dostęp tylko dla zwiedzających";
4
5console.log(poziomDostępu); // "Pełny dostęp"
6
7// Określanie komunikatu o statusie
8let liczbaOdwiedzających = 1500;
9let pojemnośćParku = 2000;
10let statusWejścia = liczbaOdwiedzających < pojemnośćParku 
11  ? "Park otwarty - Zapraszamy!" 
12  : "Park pełny - Przepraszamy, wstrzymano sprzedaż biletów.";
13
14console.log(statusWejścia); // "Park otwarty - Zapraszamy!"

Operator warunkowy może być także zagnieżdżany, choć nadmierne zagnieżdżanie może zmniejszyć czytelność kodu:

1// Zagnieżdżony operator warunkowy
2let gatunekDino = "Triceratops";
3let wiek = 5;
4let obszar = gatunekDino === "Tyranozaur" ? "Sektor T" 
5           : gatunekDino === "Velociraptor" ? "Sektor V" 
6           : gatunekDino === "Triceratops" ? (wiek < 3 ? "Sektor młodych roślinożerców" : "Sektor dorosłych roślinożerców")
7           : "Sektor ogólny";
8
9console.log(obszar); // "Sektor dorosłych roślinożerców"

Wykorzystanie wartości truthy i falsy

Jak wspomnieliśmy w poprzednich lekcjach, JavaScript traktuje różne wartości jako "prawdziwe" (truthy) lub "fałszywe" (falsy) w kontekście warunków. Możemy wykorzystać tę właściwość w instrukcjach warunkowych:

1// Sprawdzanie istnienia wartości
2let nazwaDinozaura = ""; // pusty string (falsy)
3let numerIdentyfikacyjny = 0; // zero (falsy)
4let przydzielonyObszar = null; // null (falsy)
5let daneBiometryczne; // undefined (falsy)
6let gatunekZarejestrowany = true; // wartość logiczna true (truthy)
7let notatki = "Agresywny osobnik"; // niepusty string (truthy)
8
9if (nazwaDinozaura) {
10  console.log("Nazwa dinozaura: " + nazwaDinozaura);
11} else {
12  console.log("Dinozaur nie ma przypisanej nazwy."); // to się wykona
13}
14
15if (numerIdentyfikacyjny) {
16  console.log("ID: " + numerIdentyfikacyjny);
17} else {
18  console.log("Brak prawidłowego ID."); // to się wykona
19}
20
21if (gatunekZarejestrowany && notatki) {
22  console.log("Gatunek zarejestrowany. Notatki: " + notatki); // to się wykona
23}

Podejście wczesnego zwrotu (early return)

Czasami, zamiast zagnieżdżać wiele instrukcji

if
, lepiej jest użyć podejścia wczesnego zwrotu, szczególnie w funkcjach. Polega ono na szybkim zwracaniu wyniku, gdy tylko zidentyfikujemy warunek, który na to pozwala.

1// Funkcja sprawdzająca, czy dinozaur może być przeniesiony do wybiegu publicznego
2function czyNadajeSięDoWybiegPublicznego(dinozaur) {
3  // Wczesne zwroty dla warunków wykluczających
4  if (dinozaur.poziomAgresji > 3) {
5    return false; // Zbyt agresywny
6  }
7  
8  if (dinozaur.wiek < 2) {
9    return false; // Zbyt młody
10  }
11  
12  if (dinozaur.choroby.length > 0) {
13    return false; // Ma problemy zdrowotne
14  }
15  
16  if (dinozaur.gatunekMięsożerny) {
17    // Dodatkowe warunki dla mięsożerców
18    if (dinozaur.wyszkolony && dinozaur.poziomAgresji <= 2) {
19      return true; // Wyszkolony mięsożerca o niskiej agresji
20    } else {
21      return false; // Niewyszkolony lub zbyt agresywny mięsożerca
22    }
23  }
24  
25  // Domyślnie roślinożercy są dopuszczani do wybiegu publicznego
26  return true;
27}
28
29// Przykładowe użycie
30let triceratops = {
31  gatunek: "Triceratops",
32  poziomAgresji: 2,
33  wiek: 5,
34  choroby: [],
35  gatunekMięsożerny: false,
36  wyszkolony: false
37};
38
39let velociraptor = {
40  gatunek: "Velociraptor",
41  poziomAgresji: 4,
42  wiek: 3,
43  choroby: [],
44  gatunekMięsożerny: true,
45  wyszkolony: true
46};
47
48console.log(czyNadajeSięDoWybiegPublicznego(triceratops)); // true
49console.log(czyNadajeSięDoWybiegPublicznego(velociraptor)); // false

Podsumowanie

Instrukcje warunkowe w JavaScript, podobnie jak systemy decyzyjne w Parku Jurajskim, pozwalają na:

  1. Wykonywanie kodu tylko wtedy, gdy określone warunki są spełnione (
    if
    )
  2. Wykonywanie różnych bloków kodu w zależności od warunków (
    if...else
    ,
    if...else if...else
    )
  3. Wybieranie jednego bloku kodu spośród wielu na podstawie wartości (
    switch
    )
  4. Zwracanie różnych wartości na podstawie warunku (operator warunkowy
    ? :
    )
  5. Efektywne zarządzanie złożoną logiką (wczesny zwrot, zagnieżdżone warunki)

Wybór odpowiedniej struktury warunkowej zależy od konkretnego przypadku użycia, ale generalnie należy dążyć do:

  • Używania
    if...else
    dla prostych warunków binarnych
  • Używania
    if...else if...else
    dla kilku powiązanych warunków
  • Używania
    switch
    gdy porównujemy jedną wartość z wieloma możliwymi wartościami
  • Używania operatora warunkowego dla prostych, jednoliniowych warunków
  • Unikania nadmiernego zagnieżdżania, które zmniejsza czytelność kodu

Podobnie jak systemy bezpieczeństwa w Parku Jurajskim muszą podejmować właściwe decyzje, aby zapewnić bezpieczeństwo, tak i my jako programiści musimy podejmować właściwe decyzje dotyczące struktury naszego kodu, aby zapewnić jego niezawodność i czytelność.

W następnej lekcji przyjrzymy się pętlom, które pozwalają na wielokrotne wykonywanie kodu - niezbędne np. przy przetwarzaniu danych o wielu dinozaurach jednocześnie.

Ir a CodeWorlds