Äasto potÅebujeme opakovat nÄkteré akce.
NapÅÃklad vypsat ze seznamu jedno zbožà po druhém nebo jen vykonat stejný kód pro každé z ÄÃsel od 1 do 10.
Způsob, jak opakovat stejný kód nÄkolikrát, poskytujà cykly neboli smyÄky.
Malé oznámenà pro pokroÄilé ÄtenáÅe.
Tento Älánek probÃrá jen základnà cykly: while, do..while a for(..;..;..).
Jestli jste sem pÅiÅ¡li hledat informace o jiných cyklech, najdete je zde:
- forâ¦in pro procházenà vlastnostà objektu.
- forâ¦of and iterables pro procházenà polà a iterovatelných objektů.
Jinak ÄtÄte dále.
Cyklus âwhileâ
Cyklus while má následujÃcà syntaxi:
while (podmÃnka) {
// kód
// tzv. âtÄlo cykluâ
}
Dokud je podmÃnka pravdivá, kód z tÄla cyklu se bude vykonávat.
NapÅÃklad tento cyklus vypisuje promÄnnou i tak dlouho, dokud je i < 3:
let i = 0;
while (i < 3) { // zobrazà 0, pak 1, pak 2
alert( i );
i++;
}
Jedno vykonánà tÄla cyklu se nazývá iterace. Cyklus ve výše uvedeném pÅÃkladu vykoná tÅi iterace.
Kdyby v tomto pÅÃkladu chybÄl pÅÃkaz i++, cyklus by se vykonával (teoreticky) donekoneÄna. V praxi prohlÞeÄe poskytujà způsoby, jak takový cyklus zastavit, a v JavaScriptu na serverové stranÄ můžeme proces zastavit (âshoditâ) sami.
Platnou podmÃnkou cyklu může být jakákoli promÄnná nebo výraz, nejenom porovnánÃ: pÅÃkaz while podmÃnku vyhodnotà a pÅevede na typ boolean.
NapÅÃklad while (i != 0) se dá napsat kratÅ¡Ãm způsobem jako while (i):
let i = 3;
while (i) { // když i bude 0, podmÃnka bude nepravdivá a cyklus skonÄÃ
alert( i );
i--;
}
Obsahuje-li tÄlo cyklu jen jediný pÅÃkaz, můžeme složené závorky {â¦} vynechat:
let i = 3;
while (i) alert(i--);
Cyklus âdoâ¦whileâ
OvÄÅenà podmÃnky můžeme pÅesunout až za tÄlo cyklu, použijeme-li syntaxi do..while:
do {
// tÄlo cyklu
} while (podmÃnka);
Cyklus nejprve vykoná tÄlo, pak ovÄÅà podmÃnku, a dokud je pravdivá, bude vykonávat tÄlo znovu a znovu.
PÅÃklad:
let i = 0;
do {
alert( i );
i++;
} while (i < 3);
Tuto formu syntaxe byste mÄli použÃvat jen tehdy, když chcete, aby se tÄlo cyklu vykonalo vždy aspoÅ jednou, bez ohledu na pravdivost podmÃnky. Obvykle se dává pÅednost pÅedchozà formÄ: while(â¦) {â¦}.
Cyklus âforâ
Cyklus for je složitÄjÅ¡Ã, ale také nejÄastÄji použÃvaný.
Vypadá takto:
for (zaÄátek; podmÃnka; krok) {
// ... tÄlo cyklu ...
}
Význam jednotlivých Äástà si objasnÃme na pÅÃkladu. NÞe uvedený cyklus vykoná alert(i) pro i od 0 až do (ale ne vÄetnÄ) 3:
for (let i = 0; i < 3; i++) { // zobrazà 0, pak 1, pak 2
alert(i);
}
Prozkoumáme pÅÃkaz for po Äástech:
| Äást | ||
|---|---|---|
| zaÄátek | let i = 0 |
Vykoná se jednou po vstupu do cyklu. |
| podmÃnka | i < 3 |
Kontroluje se pÅed každou iteracà cyklu. Je-li nepravdivá, cyklus skonÄÃ. |
| tÄlo | alert(i) |
Vykonává se stále znovu, dokud je podmÃnka pravdivá. |
| krok | i++ |
Vykoná se po tÄle cyklu pÅi každé iteraci. |
Všeobecný algoritmus cyklu funguje takto:
Vykonej zaÄátek
â (platÃ-li podmÃnka â vykonej tÄlo a vykonej krok)
â (platÃ-li podmÃnka â vykonej tÄlo a vykonej krok)
â (platÃ-li podmÃnka â vykonej tÄlo a vykonej krok)
â ...
To znamená, že zaÄátek se vykoná jednou a pak se iteruje: po každém testu podmÃnky se vykoná tÄlo a krok.
Jestliže s cykly teprve zaÄÃnáte, pomůže vám vrátit se k pÅÃkladu a na papÃÅe si krok po kroku projÃt, jak se vykoná.
V naÅ¡em pÅÃpadÄ se stane pÅesnÄ toto:
// for (let i = 0; i < 3; i++) alert(i)
// vykonej zaÄátek
let i = 0
// platÃ-li podmÃnka â vykonej tÄlo a vykonej krok
if (i < 3) { alert(i); i++ }
// platÃ-li podmÃnka â vykonej tÄlo a vykonej krok
if (i < 3) { alert(i); i++ }
// platÃ-li podmÃnka â vykonej tÄlo a vykonej krok
if (i < 3) { alert(i); i++ }
// ...konec, protože nynà je i == 3
âÄÃtaÄováâ promÄnná i je zde deklarována rovnou v cyklu. To se nazývá âinlineâ (na mÃstÄ) deklarace promÄnné. Takové promÄnné jsou viditelné jen uvnitÅ cyklu.
for (let i = 0; i < 3; i++) {
alert(i); // 0, 1, 2
}
alert(i); // chyba, tato promÄnná neexistuje
NamÃsto definice nové promÄnné můžeme použÃt existujÃcÃ:
let i = 0;
for (i = 0; i < 3; i++) { // použijeme existujÃcà promÄnnou
alert(i); // 0, 1, 2
}
alert(i); // 3, je viditelná, protože byla deklarována mimo cyklus
Vynechávánà ÄástÃ
Kteroukoli Äást for můžeme vynechat.
NapÅÃklad můžeme vynechat zaÄátek, jestliže nechceme na zaÄátku cyklu nic provádÄt.
NapÅÃklad zde:
let i = 0; // už máme promÄnnou i deklarovanou a pÅiÅazenou
for (; i < 3; i++) { // nepotÅebujeme âzaÄátekâ
alert( i ); // 0, 1, 2
}
Můžeme vynechat i Äást krok:
let i = 0;
for (; i < 3;) {
alert( i++ );
}
Pak bude cyklus stejný jako while (i < 3).
Ve skuteÄnosti můžeme vynechat vÅ¡echno a vytvoÅit tÃm nekoneÄnou smyÄku:
for (;;) {
// opakuje se neustále
}
VÅ¡imnÄte si, že dva stÅednÃky ; ve for musejà být uvedeny, jinak nastane syntaktická chyba.
OpuÅ¡tÄnà smyÄky
Za bÄžných okolnostà se cyklus ukonÄÃ, když jeho podmÃnka pÅestane být splnÄna.
Kdykoli si vÅ¡ak můžeme ukonÄenà vynutit použitÃm speciálnà direktivy break.
NapÅÃklad nÞe uvedený cyklus se uživatele ptá na sérii ÄÃsel, a když uživatel žádné ÄÃslo nezadá, cyklus skonÄÃ:
let souÄet = 0;
while (true) {
let hodnota = +prompt("Zadejte ÄÃslo", '');
if (!hodnota) break; // (*)
souÄet += hodnota;
}
alert( 'SouÄet: ' + souÄet );
Direktiva break na Åádku (*) se aktivuje, jestliže uživatel zadá prázdný Åádek nebo zrušà vstup. OkamžitÄ ukonÄà cyklus a pÅedá ÅÃzenà na prvnà Åádek za cyklem, konkrétnÄ alert.
Kombinace ânekoneÄná smyÄka + break, když je zapotÅebÃâ je výhodná v situacÃch, kdy potÅebujeme podmÃnku cyklu ovÄÅovat ne na zaÄátku nebo na konci cyklu, ale uprostÅed cyklu nebo dokonce na nÄkolika mÃstech jeho tÄla.
PokraÄovánà k dalšà iteraci
Direktiva continue je âslabšà verzÃâ break. Nezastavà celý cyklus, ale zastavà jen právÄ probÃhajÃcà iteraci a pÅinutà cyklus zaÄÃt novou (jestliže podmÃnka platÃ).
Můžeme ji použÃt, když jsme hotovi s právÄ probÃhajÃcà iteracà a rádi bychom okamžitÄ pÅeÅ¡li k dalÅ¡Ã.
NÞe uvedený cyklus využÃvá continue k vypsánà jen lichých hodnot:
for (let i = 0; i < 10; i++) {
// je-li podmÃnka pravdivá, pÅeskoÄÃme zbytek tÄla
if (i % 2 == 0) continue;
alert(i); // 1, pak 3, 5, 7, 9
}
Pro sudé hodnoty i direktiva continue ukonÄà vykonávánà tÄla a pÅedá ÅÃzenà dalšà iteraci for (s dalÅ¡Ãm ÄÃslem). Proto se alert bude volat jedinÄ pro liché hodnoty.
continue pomáhá redukovat vnoÅenÃCyklus, který zobrazuje liché hodnoty, by mohl vypadat i takto:
for (let i = 0; i < 10; i++) {
if (i % 2) {
alert( i );
}
}
Z technického pohledu je to stejné jako výše uvedený pÅÃklad. Bezpochyby můžeme namÃsto použità continue vnoÅit kód do bloku if.
Jako vedlejšà efekt jsme vÅ¡ak vytvoÅili jednu dalšà úroveÅ vnoÅenà (volánà alert uvnitÅ složených závorek). Je-li kód uvnitÅ if delšà než pár Åádků, může to snÞit jeho celkovou Äitelnost.
break/continue nesmÄjà být na pravé stranÄ â?âVÅ¡imnÄte si, že syntaktické konstrukce, které nejsou výrazy, nelze použÃt s ternárnÃm operátorem â?â. KonkrétnÄ tam nejsou povoleny direktivy jako break/continue.
VezmÄme si napÅÃklad tento kód:
if (i > 5) {
alert(i);
} else {
continue;
}
â¦a pÅepiÅ¡me jej pomocà otaznÃku:
(i > 5) ? alert(i) : continue; // continue tady nesmà být
â¦pÅestane to fungovat: nastane syntaktická chyba.
To je dalšà důvod, proÄ nepoužÃvat operátor otaznÃku ? namÃsto if.
NávÄÅ¡tà pro break/continue
NÄkdy se potÅebujeme dostat ven z nÄkolika vnoÅených cyklů najednou.
NapÅÃklad v nÞe uvedeném kódu vykonáváme cyklus nad i a j, který se ptá na hodnoty (i, j) od (0,0) do (2,2):
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
let vstup = prompt(`Hodnota na souÅadnicÃch (${i},${j})`, '');
// co když chceme vyskoÄit odtud až na âHotovoâ nÞe?
}
}
alert('Hotovo!');
PotÅebujeme způsob, jak tento proces zastavit, jestliže uživatel zrušà vstup.
Pouhé break po vstup by ukonÄilo jen vnitÅnà cyklus. To nám vÅ¡ak nestaÄÃ. V takovém pÅÃpadÄ použijeme návÄÅ¡tÃ.
NávÄÅ¡tà je identifikátor s dvojteÄkou pÅed cyklem:
názevNávÄÅ¡tÃ: for (...) {
...
}
PÅÃkaz break <názevNávÄÅ¡tÃ> v nÞe uvedeném cyklu vyskoÄà z uvedeného návÄÅ¡tÃ:
vnÄjÅ¡Ã: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
let vstup = prompt(`Hodnota na souÅadnicÃch (${i},${j})`, '');
// je-li zadán prázdný ÅetÄzec nebo zruÅ¡en vstup, vyskoÄà se z obou cyklů
if (!vstup) break vnÄjÅ¡Ã; // (*)
// provedeme nÄco s hodnotou...
}
}
alert('Hotovo!');
Ve výše uvedeném kódu break vnÄjšà najde návÄÅ¡tà s názvem vnÄjšà a vyskoÄà z jeho cyklu.
ÅÃzenà se tedy pÅedá pÅÃmo z (*) na alert('Hotovo!').
Můžeme návÄÅ¡tà umÃstit i na samostatný Åádek:
vnÄjÅ¡Ã:
for (let i = 0; i < 3; i++) { ... }
NávÄÅ¡tà můžeme použÃt i v direktivÄ continue. V takovém pÅÃpadÄ se zbytek kódu pÅeskoÄà a dalšà iterace bude v cyklu s uvedeným návÄÅ¡tÃm.
NávÄÅ¡tà nám neumožÅujà skákat na libovolné mÃsto v kódu.
NapÅÃklad nejde udÄlat toto:
break návÄÅ¡tÃ; // skok na návÄÅ¡tà nÞe (nebude fungovat)
návÄÅ¡tÃ: for (...)
Direktiva break musà být uvnitÅ kódového bloku. Technicky to může být jakýkoli blok kódu s návÄÅ¡tÃm, napÅ.:
návÄÅ¡tÃ: {
// ...
break návÄÅ¡tÃ; // toto funguje
// ...
}
â¦AvÅ¡ak v 99,9% pÅÃpadů se break použÃvá uvnitÅ cyklů, jak jsme vidÄli ve výše uvedených pÅÃkladech.
Direktiva continue může být jedinÄ uvnitÅ cyklu.
ShrnutÃ
Uvedli jsme tÅi druhy cyklů:
whileâ PodmÃnka se ovÄÅà pÅed každou iteracÃ.do..whileâ PodmÃnka se ovÄÅà po každé iteraci.for (;;)â PodmÃnka se ovÄÅà pÅed každou iteracÃ, jsou možná i dalšà nastavenÃ.
K vytvoÅenà ânekoneÄnéâ smyÄky se obvykle použÃvá konstrukce while(true). Takovou smyÄku lze zastavit direktivou break, stejnÄ jako každou jinou.
Pokud nechceme už nic provádÄt v souÄasné iteraci a chceme rovnou pÅejÃt k dalÅ¡Ã, použijeme direktivu continue.
break/continue podporujà návÄÅ¡tà pÅed cyklem. NávÄÅ¡tà je jediný způsob, jak může break/continue ve vnoÅeném cyklu vyskoÄit z vnÄjÅ¡Ãho cyklu.
KomentáÅe
<code>, pro nÄkolik Åádků je obalte znaÄkou<pre>, pro vÃce než 10 Åádků vložte odkaz na pÃskoviÅ¡tÄ (plnkr, jsbin, codepenâ¦)