034.3 Lecke 1
Tanúsítvány: |
Web Development Essentials |
---|---|
Verzió: |
1.0 |
Témakör: |
034 JavaScript programozás |
Fejezet: |
034.3 JavaScript vezérlési struktúrák és funkciók |
Lecke: |
1/2 |
Bevezetés
Mint minden más programozási nyelv, a JavaScript-kód is utasítások gyűjteménye, amelyek sorrendben megmondják az utasításértelmezőnek, hogy mit kell tennie. Ez azonban nem jelenti azt, hogy minden utasítást csak egyszer kell végrehajtani, vagy hogy egyáltalán bármikor végre kell hajtani. A legtöbb utasításnak csak akkor kell lefutnia, ha bizonyos feltételek teljesülnek. Még akkor is, ha egy szkriptet független események aszinkron módon indítanak el, gyakran számos vezérlő változót kell ellenőriznie, hogy megtalálja a kód megfelelő részét a futtatáshoz.
If utasítások
A legegyszerűbb vezérlési struktúrát az if
utasítás adja, amely a közvetlenül utána következő utasítást hajtja végre, ha a megadott feltétel igaz. A JavaScript akkor tekinti igaznak a feltételeket, ha a kiértékelt érték nem nulla. A if
szó utáni zárójelen belül bármi (a szóközöket leszámítva) feltételként értelmeződik. A következő példában az 1
egész szám literál a feltétel:
if ( 1 ) console.log("Az 1 mindig igaz");
Az 1
ebben a példában explicit módon szerepel, így állandó értékként kezeljük (a szkript teljes végrehajtása során ugyanaz marad), és feltételes kifejezésként használva mindig igazat ad. A true
szót (idézőjelek nélkül) is használhatjuk az 1
helyett, mivel a nyelv azt is szó szerinti igaz értékként kezeli. A console.log
utasítás a böngésző konzol ablakába írja ki az argumentumait.
Tip
|
A böngésző konzolja azokat a hibákat, figyelmeztetéseket és információs üzeneteket mutatja, amelyeket a JavaScript a |
Bár szintaktikailag helyes, a konstans kifejezések használata a feltételekben nem túl hasznos. Egy tényleges alkalmazásban valószínűleg egy változó valódiságát tesztelnénk:
let my_number = 3;
if ( my_number ) console.log("A my_number értéke", my_number, "és igazként tér vissza");
A my_number
változóhoz rendelt érték (3
) nem nulla, tehát igaz. Ez a példa azonban nem túl gyakran használható, mert ritkán kell tesztelni, hogy egy szám egyenlő-e nullával. Sokkal gyakoribb, hogy összehasonlítunk egy értéket egy másikkal, és teszteljük, hogy az eredmény igaz-e:
let my_number = 3;
if ( my_number == 3 ) console.log("A my_number értéke", my_number, "valóban");
A dupla egyenlőségjel összehasonlító operátort azért használjuk, mert az egyenlőségjel operátor már definiálva van hozzárendelési operátorként. Az operátor mindkét oldalán lévő értéket operandusnak nevezzük. Az operandusok sorrendje nem számít, és bármely kifejezés, amely értéket ad vissza, lehet operandus. Itt egy lista a többi elérhető összehasonlító operátorról:
value1 == value2
-
Igaz, ha
value1
egyenlővalue2
-vel. value1 != value2
-
Igaz, ha
value1
nem egyenlővalue2
-vel. value1 < value2
-
Igaz, ha
value1
kisebb, mintvalue2
. value1 > value2
-
Igaz, ha
value1
nagyobb, mintvalue2
. value1 <= value2
-
Igaz, ha
value1
kisebb vagy egyenlő, mintvalue2
. value1 >= value2
-
Igaz, ha
value1
nagyobb vagy egyenlő, mintvalue2
.
Általában nem számít, hogy az operátor bal oldali operandusa egy sztring, a jobb oldali operandusa pedig egy szám, amíg a JavaScript képes a kifejezést értelmes összehasonlítássá alakítani. Így az 1
karaktert tartalmazó sztringet 1-es számként fogja kezelni, ha egy számváltozóval hasonlítja össze. Annak érdekében, hogy a kifejezés csak akkor legyen igaz, ha mindkét operandus pontosan azonos típusú és értékű, az ==
helyett a szigorú azonossági operátort ===
kell használni. Hasonlóképpen, a szigorú nem-azonossági operátor !==
igaznak értékeli, ha az első operandus nem pontosan ugyanolyan típusú és értékű, mint a második operátor.
Opcionálisan az if
vezérlési struktúra egy másik utasítást is végre tud hajtani, ha a kifejezés értéke hamis:
let my_number = 4;
if ( my_number == 3 ) console.log("A my_number értéke 3");
else console.log("A my_number értéke nem 3");
Az else
utasításnak közvetlenül az if
utasítás után kell következnie. Eddig csak egy utasítást hajtunk végre, ha a feltétel teljesül. Ha egynél több utasítást szeretnénk végrehajtani, akkor azokat kapcsos zárójelek közé kell zárnunk:
let my_number = 4;
if ( my_number == 3 )
{
console.log("A my_number értéke 3");
console.log("és ez a második állítás a blokkban");
}
else
{
console.log("A my_number értéke nem 3");
console.log("és ez a második állítás a blokkban");
}
Az egy vagy több utasításból álló, kapcsos zárójelekkel határolt csoportot blokk utasításnak nevezzük. Gyakori a blokk utasítások használata akkor is, ha csak egyetlen utasítás végrehajtásáról van szó, hogy a kódolási stílus egységes legyen az egész szkriptben. A JavaScript egyébként nem követeli meg, hogy a kapcsos zárójelek vagy bármelyik utasítás külön sorban legyen, de ha így írjuk, az javítja az olvashatóságot és megkönnyíti a kód karbantartását.
A vezérlési struktúrák egymásba ágyazhatók, de fontos, hogy ne keverjük össze az egyes blokkutasítások nyitó és záró zárójeleit:
let my_number = 4;
if ( my_number > 0 )
{
console.log("A my_number értéke pozitív");
if ( my_number % 2 == 0 )
{
console.log("és páros szám");
}
else
{
console.log("és páratlan szám");
}
} // end of if ( my_number > 0 )
else
{
console.log("A my_number értéke kisebb vagy egyenlő 0");
console.log("ezért figyelmen kívül hagyom");
}
Az if
utasítás által kiértékelt kifejezések azonban sokkal bonyolultabbak is lehetnek az egyszerű összehasonlításoknál. Ez a helyzet az előző példában, ahol a my_number % 2
aritmetikai kifejezést használtuk a zárójelek között a beágyazott if
utasításban. A %
operátor a bal oldali számnak a jobb oldali számmal való osztása utáni maradékot adja vissza. Az olyan aritmetikai operátorok, mint a %
, elsőbbséget élveznek az olyan összehasonlító operátorokkal szemben, mint az ==
, így az összehasonlítás az aritmetikai kifejezés eredményét használja bal oldali operandusként.
Sok helyzetben az egymásba ágyazott feltételes struktúrák egyetlen struktúrává kombinálhatók a logikai operátorok segítségével. Ha például csak a pozitív páros számok érdekelnének minket, akkor egyetlen if
struktúrát használhatnánk:
let my_number = 4;
if ( my_number > 0 && my_number % 2 == 0 )
{
console.log("A my_number értéke pozitív");
console.log("és páros szám");
}
else
{
console.log("A my_number értéke vagy 0, vagy negatív");
console.log("vagy negatív szám");
}
A kiértékelt kifejezésben szereplő dupla és &&
operátor a logikai AND operátor. Csak akkor lesz igaz, ha a tőle balra lévő kifejezés és a tőle jobbra lévő kifejezés is igaz. Ha pozitív vagy páros számokat szeretnénk összehasonlítani, akkor a ||
operátort kell használni helyette, amely az OR logikai operátort jelenti:
let my_number = -4;
if ( my_number > 0 || my_number % 2 == 0 )
{
console.log("A my_number értéke pozitív");
console.log("vagy egy páros negatív szám");
}
Ebben a példában csak a negatív páratlan számok nem felelnek meg az összetett kifejezés által meghatározott feltételeknek. Ha az ellenkezőjét szeretnénk elérni, azaz azt, hogy csak a negatív páratlan számok feleljenek meg, akkor a kifejezés elejére tegyük a !
logikai NOT operátort:
let my_number = -5;
if ( ! ( my_number > 0 || my_number % 2 == 0 ) )
{
console.log("A my_number értéke egy negatív páratlan szám");
}
A zárójelek hozzáadása az összetett kifejezéshez arra kényszeríti a zárójelek által körülvett kifejezést, hogy először az kerüljön kiértékelésre. A zárójelek nélkül a NOT operátor csak a my_number > 0
kifejezésre vonatkozna, és csak ezután kerülne kiértékelésre az OR kifejezés. A &&
és a ||
operátorokat bináris logikai operátoroknak nevezzük, mivel két operandusra van szükségük. A !
egyértékű logikai operátor, mert csak egy operandusra van szükség.
Switch struktúrák
Bár az if
struktúra elég sokoldalú és elegendő lehet a program folyamának vezérlésére, a switch
vezérlési struktúra megfelelőbb lehet, ha igaz vagy hamis eredménytől eltérő eredményeket kell kiértékelnünk. Ha például egy listából kiválasztott minden egyes elemre külön műveletet akarunk végrehajtani, akkor minden egyes értékeléshez egy if
struktúrát kell írni:
// Elérhető nyelvek: en (angol), es (spanyol), pt (portugál)
let language = "pt";
// Változó annak regisztrálására, hogy a nyelv megtalálható-e a listán
let found = 0;
if ( language == "en" )
{
found = 1;
console.log("angol");
}
if ( found == 0 && language == "es" )
{
found = 1;
console.log("spanyol");
}
if ( found == 0 && language == "pt" )
{
found = 1;
console.log("portugál");
}
if ( found == 0 )
{
console.log(language, " ismeretlen");
}
Ebben a példában a found
segédváltozót minden if
struktúra használja, hogy kiderítse, van-e találat. Az ehhez hasonló esetekben a switch
struktúra ugyanezt a feladatot végzi el, de sokkal tömörebb módon:
switch ( language )
{
case "en":
console.log("angol");
break;
case "es":
console.log("spanyol");
break;
case "pt":
console.log("portugál");
break;
default:
console.log(language, " nem található");
}
Minden egyes egymásba ágyazott case
-t feltételnek (clause) nevezünk. Ha egy feltétel megfelel az értékelt kifejezésnek, akkor a kettőspontot követő utasításokat hajtja végre a break
utasításig. Az utolsó feltételben nincs szükség break
utasításra, és ezt gyakran használjuk az alapértelmezett művelet beállítására, ha nincs találat. Amint a példában látható, a switch
szerkezetben nincs szükség a segédváltozóra.
Warning
|
A |
Ha egynél több feltétel triggereli ugyanazt a műveletet, akkor két vagy több case
feltétel kombinálható:
switch ( language )
{
case "en":
case "en_US":
case "en_GB":
console.log("angol");
break;
case "es":
console.log("spanyol");
break;
case "pt":
case "pt_BR":
console.log("portugál");
break;
default:
console.log(language, " nem található");
}
Ciklusok
Az előző példákban látható if
és switch
struktúrák jól alkalmazhatóak olyan feladatokhoz, amelyeknek egy vagy több feltételes teszt teljesítése után csak egyszer kell lefutniuk. Vannak azonban olyan helyzetek, amikor egy feladatnak ismételten - egy úgynevezett loop-ban (ciklusban) - kell végrehajtódnia mindaddig, amíg a feltételes kifejezés igaznak nem bizonyul. Ha például tudnunk kell, hogy egy szám prím-e, akkor azt kell ellenőriznünk, hogy ha ezt a számot elosztjuk bármely egész számmal, amely nagyobb, mint 1 és kisebb, mint önmaga, akkor a maradék értéke 0-e. Ha igen, akkor a számnak van egy egész számú tényezője, és nem prím. (Ez nem egy szigorú vagy hatékony módszer a prímszámok megtalálására, de egyszerű példaként használható). Ilyen esetekre alkalmasabbak a ciklusvezérlő struktúrák, különösen a while
utasítás:
// Egy egyszerű prímszám-tesztelő
// A kiértékelni kívánt szám
let candidate = 231;
// Segédváltozó
let is_prime = true;
// Az első kipróbálandó tényező
let factor = 2;
// Végrehajtja a blokk utasítást, ha a factor
// kisebb, mint a candidate, és folytatja a műveletet
// amíg a factor kisebb, mint a candidate
while ( factor < candidate )
{
if ( candidate % factor == 0 )
{
// A maradék nulla, tehát a candidate nem prímszám.
is_prime = false;
break;
}
// A következő tényező, amit ki kell próbálni. Egyszerűen
// növeljük az aktuális tényezőt eggyel
factor++;
}
// Írjuk ki az eredményt a konzolra.
// Ha a jelöltnek nincs egész számú tényezője, akkor
// az is_prime segédváltozó még mindig igaz.
if ( is_prime )
{
console.log(candidate, "prímszám");
}
else
{
console.log(candidate, "nem prímszám");
}
A while
utasítást követő blokk ismételten végrehajtódik addig, amíg a factor < candidate
feltétel igaz. Legalább egyszer végrehajtódik, amíg a factor
változót a candidate
értéknél kisebb értékkel inicializáljuk. A while
struktúrába ágyazott if
kiértékeli, hogy a candidate
factor
-ral való osztása esetén nulla-e a maradék. Ha igen, akkor a jelölt szám nem prímszám, és a ciklus befejeződhet. A break
utasítás befejezi a ciklust, és a végrehajtás a while
blokk utáni első utasításra ugrik.
Vegyük figyelembe, hogy a while
utasítás által használt feltétel eredményének minden ciklusban változnia kell, különben a blokk utasítás örökké
fog tartani. A példában a factor
változót -a következő osztót, amellyel próbálkozni akarunk- növeljük, és ez garantálja, hogy a ciklus egy ponton véget fog érni.
A prímszámtesztelő egyszerű megvalósítása tehát a várakozásoknak megfelelően működik. Azonban tudjuk, hogy egy olyan szám, amely nem osztható kettővel, nem lesz osztható semmilyen más páros számmal sem. Ezért egy újabb if
utasítás hozzáadásával egyszerűen kihagyhatjuk a páros számokat:
while ( factor < candidate )
{
// Hagyjuk ki a kettőnél nagyobb páros számokat
if ( factor > 2 && factor % 2 == 0 )
{
factor++;
continue;
}
if ( candidate % factor == 0 )
{
// A maradék nulla, tehát a candidate nem prímszám.
is_prime = false;
break;
}
// A következő szám, amivel osztjuk a candidate számot
factor++;
}
A continue
utasítás hasonló a break
utasításhoz, de ahelyett, hogy befejezné a ciklus ismétlését, figyelmen kívül hagyja a ciklus többi blokkját, és új iterációba kezd. Vegyük észre, hogy a factor
változót a continue
utasítás előtt módosítottuk, különben a ciklus a következő iterációban ismét ugyanezzel az eredménnyel járna. Ez a példa túl egyszerű, és a ciklus egy részének kihagyása nem igazán javítja a teljesítményét, de a felesleges utasítások kihagyása nagyon fontos a hatékony alkalmazások írásakor.
A ciklusok annyira elterjdtek, hogy többféle változatuk is van. A for
ciklus különösen alkalmas a szekvenciális értékek végigjárására (végigiterálására), mert lehetővé teszi, hogy a ciklus szabályait egyetlen sorban definiáljuk:
for ( let factor = 2; factor < candidate; factor++ )
{
// Hagyjuk ki a kettőnél nagyobb páros számokat
if ( factor > 2 && factor % 2 == 0 )
{
continue;
}
if ( candidate % factor == 0 )
{
// A maradék 0, tehát a candidate nem prímszám
is_prime = false;
break;
}
}
Ez a példa pontosan ugyanazt az eredményt adja, mint az előző while
, de a zárójeles kifejezés három, pontosvesszővel elválasztott részt tartalmaz: az inicializálást (let factor = 2
), a ciklusfeltételt (factor < candidate
) és a ciklus minden egyes ismétlésének végén kiértékelendő végső kifejezést (factor+`). A `continue` és `break` utasítások a `for` ciklusokban is használhatók. A zárójelben lévő végső kifejezés (`factor+
) a continue
utasítás után kerül kiértékelésre, tehát nem lehet a blokkon belül, különben a következő iteráció előtt kétszer növekedne az értéke.
A JavaScript speciális for
ciklusokkal rendelkezik a tömbszerű objektumokkal való munkához. Így például változó helyett egy jelölteket (candidates) tartalmazó tömböt is ellenőrizhetünk:
// Egy egyszerű prímszám-tesztelő
// A kiértékelni kívánt számokat tartalmazó tömb
let candidates = [111, 139, 293, 327];
// Kiértékeli a tömbben levő összes jelöltet
for (candidate of candidates)
{
// Auxiliary variable
let is_prime = true;
for ( let factor = 2; factor < candidate; factor++ )
{
// Hagyjuk ki a kettőnél nagyobb páros számokat
if ( factor > 2 && factor % 2 == 0 )
{
continue;
}
if ( candidate % factor == 0 )
{
// A maradék nulla, tehát a candidate nem prímszám
is_prime = false;
break;
}
}
// Írjuk ki az eredményt a konzolra
if ( is_prime )
{
console.log(candidate, "prímszám");
}
else
{
console.log(candidate, "nem prímszám");
}
}
A for (candidate of candidates)
utasítás a candidates
(jelöltek) tömb egy elemét hozzárendeli a candidate
változóhoz, és azt használja a blokk utasításban, megismételve a folyamatot a tömb minden elemére. Nem kell külön deklarálnunk a candidate
(jelölt) változót, mert a for
ciklus definiálja azt. Végül ugyanezt a kódot az előző példából beágyaztuk ebbe az új blokkutasításba, de ezúttal a tömb minden egyes jelöltjét teszteljük.
Gyakorló feladatok
-
A
my_var
változó mely értékei felelnek meg amy_var > 0 && my_var < 9
feltételnek? -
A
my_var
változó mely értékei felelnek meg amy_var > 0 || my_var < 9
feltételnek? -
Hányszor hajtja végre a következő
while
ciklus a blokk utasítását?let i = 0; while ( 1 ) { if ( i == 10 ) { continue; } i++; }
Gondolkodtató feladatok
-
Mi történik, ha az egyenlőségjel hozzárendelési operátort
=
használjuk az egyenlőségjel összehasonlítási operátor==
helyett? -
Írjunk egy kódrészletet az
if
vezérlési struktúrát használva, ahol az egyszerű egyenlőségi összehasonlítás igazat ad vissza, de a szigorú egyenlőségi összehasonlítás nem! -
Írjuk át a következő
for
utasítást a ciklusfeltételben az unáris NOT logikai operátor használatával! A feltétel eredményének ugyanannak kell lennie.for ( let factor = 2; factor < candidate; factor++ )
-
A lecke példái alapján írjunk egy olyan ciklusvezérlő struktúrát, amely kiírja egy adott szám összes egész számtényezőjét!
Összefoglalás
Ez a lecke a vezérlési struktúrák JavaScript-kódban való használatát tárgyalja. A feltétel- és ciklusszerkezetek minden programozási paradigma alapvető elemei, és ez alól a JavaScript webfejlesztés sem kivétel. Ez a lecke a következő eljárásokat és fogalmakat veszi át:
-
Az
if
utasítás és az összehasonlító operátorok. -
Hogy használjuk a
switch
struktúrát acase
,default
, ésbreak
elemekkel. -
A különbség az egyszerű és a szigorú összehasonlítás között.
-
Ciklusvezérlő struktúrák:
while
ésfor
.
Válaszok a gyakorló feladatokra
-
A
my_var
változó mely értékei felelnek meg amy_var > 0 && my_var < 9
feltételnek?Csak azok a számok, amelyek nagyobbak 0-nál és kisebbek 9-nél. Az
&&
(AND) logikai operátor esetén mindkét feltételnek teljesülnie kell. -
A
my_var
változó mely értékei felelnek meg amy_var > 0 || my_var < 9
feltételnek?A
||
(OR) logikai operátornál bármelyik szám megfelel, mivel bármelyik szám nagyobb lesz 0-nál vagy kisebb 9-nél. -
Hányszor hajtja végre a következő
while
ciklus a blokk utasítását?let i = 0; while ( 1 ) { if ( i == 10 ) { continue; } i++; }
A blokk utasítás a végtelenségig ismétlődik, mivel nem adtunk megállási feltételt.
Válaszok a gondolkodtató feladatokra
-
Mi történik, ha az egyenlőségjel hozzárendelési operátort
=
használjuk az egyenlőségjel összehasonlítási operátor==
helyett?Az operátor jobb oldalán lévő értéket hozzárendeli a bal oldali változóhoz, és ezt az eredményt adja át összehasonlításra, ami nem biztos, hogy a kívánt viselkedés.
-
Írjunk egy kódrészletet az
if
vezérlési struktúrát használva, ahol az egyszerű egyenlőségi összehasonlítás igazat ad vissza, de a szigorú egyenlőségi összehasonlítás nem!let a = "1"; let b = 1; if ( a == b ) { console.log("Az egyszerű összehasonlítás igaz lesz."); } if ( a === b ) { console.log("A szigorú összehasonlítás hamis lesz."); }
-
Írjuk át a következő
for
utasítást a ciklusfeltételben az unáris NOT logikai operátor használatával! A feltétel eredményének ugyanannak kell lennie.for ( let factor = 2; factor < candidate; factor++ )
Válasz:
for ( let factor = 2; ! (factor >= candidate); factor++ )
-
A lecke példái alapján írjunk egy olyan ciklusvezérlő struktúrát, amely kiírja egy adott szám összes egész számtényezőjét!
for ( let factor = 2; factor <= my_number; factor++ ) { if ( my_number % factor == 0 ) { console.log("A " factor, "a", my_number ", egész számtényezője"); } }