1. blokk · Alapok · 4. fejezet
Egy program ritkán fut le egyenes vonalban: néha elágazik (ha igaz a feltétel,
csináld ezt, különben azt), néha pedig ismétel valamit sokszor. Ebben a fejezetben az
if/else, a switch és a
ciklusok (while, for) kerülnek sorra — és a
három alapminta, amelyre szinte minden algoritmus épül: számlálás, összegzés, keresés.
A vezérlési szerkezetek irányítják, hogy a kód mely része és hányszor fusson le. Két fő fajtájuk van:
if, else, switch.while, for.A feltételek a 3. fejezetből ismert összehasonlító és logikai operátorokat használják
(===, >, &&, ||, !).
Az if akkor futtatja a kapcsos zárójelben lévő kódot, ha a feltétel igaz.
Az else a „különben" ág, az else if pedig további eseteket vizsgál:
let kor = 17; if (kor >= 18) { console.log("Nagykorú"); } else if (kor >= 14) { console.log("Fiatalkorú"); } else { console.log("Gyermek"); }
A JavaScript fentről lefelé vizsgálja a feltételeket, és az első igaznál megáll — a többi ágat már nem is nézi.
Ha egyik sem igaz, az else ág fut le (ha van). Ezért számít a sorrend: a fenti példában ha
előbb a kor >= 14-et vizsgálnánk, a 20 évesek is „fiatalkorúak" lennének.
Az if törzsét akkor is érdemes kapcsos zárójelbe tenni, ha csak egy sor — így később biztonságosan bővíthető, és olvashatóbb.
Nem csak összehasonlítás állhat a zárójelben: a 3. fejezetből ismert truthy/falsy szabály szerint
bármilyen érték feltétel lehet. A 0, az üres szöveg, a null és az
undefined hamisnak számít:
let keszlet = 0; if (keszlet) { // 0 → hamis console.log("Van raktáron"); } else { console.log("Elfogyott"); // ez fut le }
Ha egyetlen érték sokféle konkrét esetét kell kezelni, a switch áttekinthetőbb, mint sok else if:
let statusz = "feldolgozas"; switch (statusz) { case "uj": console.log("Új rendelés"); break; case "feldolgozas": console.log("Feldolgozás alatt"); break; case "kesz": case "kiszallitva": // két eset, ugyanaz a teendő console.log("Lezárt rendelés"); break; default: console.log("Ismeretlen állapot"); }
Minden case végére kell egy break, különben a futás „átcsorog" a következő
case-re is. Ezt csak akkor használjuk szándékosan, ha több eset ugyanazt csinálja (mint fent a
"kesz" és a "kiszallitva"). A switch szigorú
(===) összehasonlítást használ.
A while addig ismétli a törzsét, amíg a feltétel igaz. A feltételt minden kör elején ellenőrzi:
let i = 1; while (i <= 3) { console.log("Kör: " + i); i++; // FONTOS: a feltétel felé léptetünk! } // Kör: 1, Kör: 2, Kör: 3
A while akkor a kézenfekvő, ha nem tudjuk előre, hány kör lesz — pl. addig
osztunk egy számot 10-zel, amíg el nem fogy:
let n = 4721; let szamjegyek = 0; while (n > 0) { n = Math.floor(n / 10); // 472, 47, 4, 0 szamjegyek++; } console.log(szamjegyek); // 4
Ha a feltétel sosem válik hamissá (pl. elfelejted az i++-t), a ciklus végtelenül fut.
Node-ban a program „beragad" és csak Ctrl+C-vel állítható le. Az itteni gyakorló 3 másodperc után
leállítja a kódot és szól — de mindig gondoskodj róla, hogy a feltétel egyszer hamis legyen!
A do…while a feltételt a kör végén ellenőrzi — ezért a törzs legalább egyszer
mindig lefut, akkor is, ha a feltétel már az elején hamis:
let i = 10; do { console.log("Ez egyszer biztosan lefut"); i++; } while (i < 3); // a feltétel hamis, de a törzs egyszer már lefutott
A for a leggyakoribb ciklus, amikor tudjuk, hányszor akarunk ismételni. Egy sorban tartalmazza a három részt:
for (let i = 1; i <= 5; i++) { console.log(i); } // └─kezdés──┘ └─feltétel─┘ └léptetés┘
| Rész | Mit csinál | Mikor fut |
|---|---|---|
let i = 1 | kezdőérték | egyszer, a legelején |
i <= 5 | feltétel | minden kör előtt |
i++ | léptetés | minden kör végén |
A léptetés nem csak i++ lehet: visszafelé is számolhatunk, és nagyobb lépésközzel is:
for (let i = 10; i >= 0; i -= 2) { console.log(i); // 10, 8, 6, 4, 2, 0 }
A for…of egy gyűjtemény (pl. szöveg vagy tömb) minden elemén végigmegy, anélkül hogy indexet kéne
számolnunk. Tömbökkel a 6. fejezetben dolgozunk, de szövegen már most kipróbálhatod:
let szo = "alma"; for (let betu of szo) { console.log(betu); // a, l, m, a }
A ciklusos feladatok döntő többsége három egyszerű mintára vezethető vissza. Ha ezeket felismered, a feladatok nagy része „magától" megíródik. Mindhárom lényege: a ciklus előtt létrehozunk egy változót, a ciklusban frissítjük, a ciklus után kiírjuk.
let db = 0; // 1) gyűjtő 0-ról indul for (let i = 1; i <= 20; i++) { if (i % 3 === 0) { db++; // 2) ha megfelel, +1 } } console.log(db); // 3) eredmény: 6
let osszeg = 0; // 1) gyűjtő 0-ról indul for (let i = 1; i <= 100; i++) { osszeg += i; // 2) hozzáadjuk } console.log(osszeg); // 3) eredmény: 5050
Amikor azt kérdezzük, hogy létezik-e egy tulajdonságú elem, egy logikai „kapcsolót" használunk: hamisról indul, és ha találunk egyet, igazra billentjük. Példa: osztható-e a szám 1-nél és önmagánál kívül bármivel?
let n = 91; let vanOszto = false; // 1) kapcsoló: még nem találtunk for (let i = 2; i < n; i++) { if (n % i === 0) { vanOszto = true; // 2) találat → átbillentjük break; // tovább nem is kell keresni } } console.log(vanOszto ? "összetett" : "prím"); // 3) 91 = 7 · 13 → összetett
Rokon minta a legnagyobb / legkisebb keresése: a gyűjtő az első elemről (vagy egy biztosan „rossz" értékről) indul, és minden körben lecseréljük, ha jobbat találunk.
Egy Express-szerverben pontosan ezekkel a mintákkal számoljuk meg egy rendelés tételeit, összegezzük a kosár értékét,
vagy keressük meg, van-e már ilyen e-mail-cím a felhasználók között. Később a tömb-metódusok (filter,
reduce, some) rövidebben írják le ugyanezt — de mindegyik alatt ez a három minta van.
Egy ciklus törzsében újabb ciklus is állhat. A belső ciklus a külső minden egyes körében teljesen lefut — így pl. egy 3 soros, 5 oszlopos „táblázatot" 3 · 5 = 15 lépésben járunk be:
for (let sor = 1; sor <= 3; sor++) { let szoveg = ""; for (let oszlop = 1; oszlop <= 5; oszlop++) { szoveg += "*"; // a belső ciklus egy sort épít fel } console.log(szoveg); // a külső ciklus soronként ír ki } // ***** // ***** // *****
Ha a belső ciklus határa a külső változótól függ, háromszöget kapunk — ez a klasszikus „csillag-piramis" feladatok kulcsa:
for (let sor = 1; sor <= 4; sor++) { let szoveg = ""; for (let j = 1; j <= sor; j++) { // annyi csillag, amennyi a sor száma szoveg += "*"; } console.log(szoveg); } // * // ** // *** // ****
A külső és a belső ciklus változójának különböző név kell (i és j,
vagy még jobb: sor és oszlop). Ha mindkettő i, a belső
elfedi a külsőt, és nagyon nehezen megtalálható hibát kapsz.
Két parancs a ciklus futásának finomhangolására:
| Parancs | Mit csinál |
|---|---|
break | Kilép a ciklusból azonnal (a hátralévő körök is elmaradnak). |
continue | Az aktuális kört hagyja ki, és a következő körrel folytatja. |
for (let i = 1; i <= 5; i++) { if (i === 3) continue; // a 3-at kihagyja if (i === 5) break; // 5-nél kilép console.log(i); // 1, 2, 4 }
Egymásba ágyazott ciklusnál a break csak a belső ciklusból lép ki — a külső folytatódik.
Kísérletezz az elágazásokkal és a ciklusokkal! Írd át a feltételeket és a határokat, és nézd meg, mi változik a kimenetben.
A kimenet úgy jelenik meg, ahogy Node-ban a console.log mutatná.
Válassz mintát vagy írj sajátot — majd Futtatás (Ctrl+Enter) ↓
Apró algoritmikus feladatok, csak az eddig tanultakkal (változók, operátorok, elágazás, ciklus). Minden feladatnál a Futtatás az első példa-bemenettel futtatja a kódod, az Ellenőrzés pedig több bemenettel is kipróbálja, és összeveti a kimenetet a várttal. Az adott változókat a gyakorló hozza létre — te csak használd őket.
⭐ alap · ⭐⭐ haladó · ⭐⭐⭐ kihívás — a haladásod ebben a böngészőben megmarad.
1) Írd le magadnak egy mondatban, mi a bemenet és mi a kimenet. 2) Döntsd el, elágazás vagy ciklus kell-e (vagy mindkettő). 3) Ha ciklus: melyik alapminta — számlálás, összegzés, keresés? 4) Csak ezután írj kódot, és futtasd gyakran!
if / else if / else — az első igaz feltételnél áll meg, ezért számít a sorrend; switch egy érték sok esetére.switch-ben minden case végére kell break; a default a „többi eset".while (feltétel elöl, ismeretlen körszám), do…while (legalább egyszer fut), for (kezdés; feltétel; léptetés — ismert körszám).for…of egy gyűjtemény minden elemén végigmegy.db++), összegzés (osszeg += x), keresés (logikai kapcsoló vagy legjobb-eddig változó). Gyűjtő a ciklus előtt, frissítés a ciklusban, kiírás a ciklus után.break = kilép a ciklusból; continue = a következő körre ugrik. Vigyázz a végtelen ciklusra!A logika és az ismétlés megvan — a következő fejezetben a függvényekkel rendszerezzük a kódot: újrahasználható, névvel ellátott kódblokkokba, paraméterekkel és visszatérési értékkel. Onnantól a feladatokban függvényeket írsz, amelyeket az ellenőrző közvetlenül meghív.