Smyčky:while a for

Často musíme akce opakovat.

Například výstup zboží ze seznamu jeden po druhém nebo jen spuštění stejného kódu pro každé číslo od 1 do 10.

Smyčky představují způsob, jak opakovat stejný kód vícekrát.

Smyčky for...of a for...in

Malé oznámení pro pokročilé čtenáře.

Tento článek se zabývá pouze základními smyčkami:while , do..while a for(..;..;..) .

Pokud jste se dostali k tomuto článku při hledání jiných typů smyček, zde jsou odkazy:

  • Podívejte se na…in pro opakování vlastností objektu.
  • Viz…of a iterables pro opakování přes pole a iterovatelné objekty.

V opačném případě čtěte dále.

Smyčka „while“

while smyčka má následující syntaxi:

while (condition) {
 // code
 // so-called "loop body"
}

Zatímco condition je pravda, code z těla smyčky.

Například smyčka pod výstupem i zatímco i < 3 :

let i = 0;
while (i < 3) { // shows 0, then 1, then 2
 alert( i );
 i++;
}

Jedno provedení těla smyčky se nazývá iterace . Smyčka ve výše uvedeném příkladu tvoří tři iterace.

Pokud i++ chyběl ve výše uvedeném příkladu, smyčka by se opakovala (teoreticky) navždy. V praxi prohlížeč poskytuje způsoby, jak zastavit takové smyčky, a v JavaScriptu na straně serveru můžeme proces ukončit.

Jakýkoli výraz nebo proměnná může být podmínkou smyčky, nejen porovnání:podmínka je vyhodnocena a převedena na logickou hodnotu pomocí while .

Například kratší způsob zápisu while (i != 0) je while (i) :

let i = 3;
while (i) { // when i becomes 0, the condition becomes falsy, and the loop stops
 alert( i );
 i--;
}
Pro jednořadé tělo nejsou složené závorky vyžadovány

Pokud má tělo smyčky jeden příkaz, můžeme vynechat složené závorky {…} :

let i = 3;
while (i) alert(i--);

Smyčka „do...while“

Kontrolu stavu lze přesunout níže tělo smyčky pomocí do..while syntaxe:

do {
 // loop body
} while (condition);

Cyklus nejprve provede tělo, poté zkontroluje podmínku, a pokud je pravdivá, provede ji znovu a znovu.

Například:

let i = 0;
do {
 alert( i );
 i++;
} while (i < 3);

Tato forma syntaxe by měla být použita pouze v případě, že chcete, aby se tělo smyčky provedlo alespoň jednou bez ohledu na to, zda je podmínka pravdivá. Obvykle je preferován jiný tvar:while(…) {…} .

Smyčka „for“

for smyčka je složitější, ale je to také nejčastěji používaná smyčka.

Vypadá to takto:

for (begin; condition; step) {
 // ... loop body ...
}

Naučme se význam těchto částí na příkladu. Smyčka níže běží alert(i) pro i z 0 až (ale ne včetně) 3 :

for (let i = 0; i < 3; i++) { // shows 0, then 1, then 2
 alert(i);
}

Podívejme se na for výpis po částech:

část
začít let i = 0 Spustí se jednou při vstupu do smyčky.
podmínka i < 3 Kontrolováno před každou iterací smyčky. Pokud je false, smyčka se zastaví.
tělo alert(i) Běží znovu a znovu, dokud je podmínka pravdivá.
krok i++ Spustí se po těle při každé iteraci.

Algoritmus obecné smyčky funguje takto:

Run begin
→ (if condition → run body and run step)
→ (if condition → run body and run step)
→ (if condition → run body and run step)
→ ...

To znamená begin provede se jednou a poté se opakuje:po každém condition test, body a step jsou provedeny.

Pokud jste se smyčkami nováčkem, mohlo by vám pomoci vrátit se k příkladu a zopakovat si, jak to běží, krok za krokem na kus papíru.

Zde je přesně to, co se stane v našem případě:

// for (let i = 0; i < 3; i++) alert(i)

// run begin
let i = 0
// if condition → run body and run step
if (i < 3) { alert(i); i++ }
// if condition → run body and run step
if (i < 3) { alert(i); i++ }
// if condition → run body and run step
if (i < 3) { alert(i); i++ }
// ...finish, because now i == 3
Inline deklarace proměnné

Zde je proměnná „počítadla“ i je deklarován přímo ve smyčce. Toto se nazývá „inline“ deklarace proměnné. Takové proměnné jsou viditelné pouze uvnitř smyčky.

for (let i = 0; i < 3; i++) {
 alert(i); // 0, 1, 2
}
alert(i); // error, no such variable

Místo definování proměnné bychom mohli použít existující:

let i = 0;

for (i = 0; i < 3; i++) { // use an existing variable
 alert(i); // 0, 1, 2
}

alert(i); // 3, visible, because declared outside of the loop

Přeskočení částí

Jakákoli část for lze přeskočit.

Můžeme například vynechat begin pokud na začátku smyčky nepotřebujeme nic dělat.

Jako zde:

let i = 0; // we have i already declared and assigned

for (; i < 3; i++) { // no need for "begin"
 alert( i ); // 0, 1, 2
}

Můžeme také odstranit step část:

let i = 0;

for (; i < 3;) {
 alert( i++ );
}

Díky tomu je smyčka identická s while (i < 3) .

Můžeme vlastně odstranit všechno a vytvořit tak nekonečnou smyčku:

for (;;) {
 // repeats without limits
}

Vezměte prosím na vědomí, že dva for středníky ; musí být přítomen. Jinak by došlo k chybě syntaxe.

Přerušení smyčky

Normálně se smyčka ukončí, když se její stav stane chybným.

Můžeme však kdykoli vynutit ukončení pomocí speciálního break směrnice.

Například smyčka níže žádá uživatele o řadu čísel, která se „přeruší“, když není zadáno žádné číslo:

let sum = 0;

while (true) {

 let value = +prompt("Enter a number", '');

 if (!value) break; // (*)

 sum += value;

}
alert( 'Sum: ' + sum );

break direktiva je aktivována na řádku (*) pokud uživatel zadá prázdný řádek nebo zruší zadání. Okamžitě zastaví smyčku a předá řízení prvnímu řádku za smyčkou. Konkrétně alert .

Kombinace „nekonečná smyčka + break podle potřeby“ je skvělé pro situace, kdy je nutné zkontrolovat stav smyčky ne na začátku nebo na konci smyčky, ale uprostřed nebo dokonce na několika místech jejího těla.

Pokračovat na další iteraci

continue direktiva je „odlehčenou verzí“ break . Nezastaví celou smyčku. Místo toho zastaví aktuální iteraci a vynutí smyčku, aby zahájila novou (pokud to podmínka umožňuje).

Můžeme ji použít, pokud jsme s aktuální iterací hotovi a chtěli bychom přejít k další.

Smyčka níže používá continue pro výstup pouze liché hodnoty:

for (let i = 0; i < 10; i++) {

 // if true, skip the remaining part of the body
 if (i % 2 == 0) continue;

 alert(i); // 1, then 3, 5, 7, 9
}

Pro sudé hodnoty i , continue direktiva zastaví provádění těla a předá řízení další iteraci for (s dalším číslem). Takže alert je voláno pouze pro liché hodnoty.

continue direktiva pomáhá snížit vnořování

Smyčka, která ukazuje liché hodnoty, může vypadat takto:

for (let i = 0; i < 10; i++) {

 if (i % 2) {
 alert( i );
 }

}

Z technického hlediska je to totožné s příkladem výše. Jistě, můžeme jen zabalit kód do if blok místo použití continue .

Ale jako vedlejší efekt to vytvořilo další úroveň vnoření (alert volání uvnitř složených závorek). Pokud je kód uvnitř if je delší než několik řádků, což může snížit celkovou čitelnost.

Ne break/continue napravo od ‚?‘

Vezměte prosím na vědomí, že konstrukce syntaxe, které nejsou výrazy, nelze použít s ternárním operátorem ? . Zejména direktivy jako break/continue tam nejsou povoleny.

Vezmeme-li například tento kód:

if (i > 5) {
 alert(i);
} else {
 continue;
}

…a přepište jej pomocí otazníku:

(i > 5) ? alert(i) : continue; // continue isn't allowed here

…přestane fungovat:došlo k chybě syntaxe.

To je jen další důvod, proč nepoužívat operátor s otazníkem ? místo if .

Štítky pro přerušení/pokračování

Někdy se potřebujeme vymanit z více vnořených smyček najednou.

Například v níže uvedeném kódu procházíme smyčkou i a j s výzvou k zadání souřadnic (i, j) od (0,0) na (2,2) :

for (let i = 0; i < 3; i++) {

 for (let j = 0; j < 3; j++) {

 let input = prompt(`Value at coords (${i},${j})`, '');

 // what if we want to exit from here to Done (below)?
 }
}

alert('Done!');

Potřebujeme způsob, jak zastavit proces, pokud uživatel zruší vstup.

Obyčejný break po input pouze by přerušil vnitřní smyčku. To nestačí – štítky, přijďte na pomoc!

štítek je identifikátor s dvojtečkou před smyčkou:

labelName: for (...) {
 ...
}

break <labelName> příkaz ve smyčce níže se rozdělí na štítek:

outer: for (let i = 0; i < 3; i++) {

 for (let j = 0; j < 3; j++) {

 let input = prompt(`Value at coords (${i},${j})`, '');

 // if an empty string or canceled, then break out of both loops
 if (!input) break outer; // (*)

 // do something with the value...
 }
}

alert('Done!');

Ve výše uvedeném kódu break outer hledá štítek s názvem outer směrem nahoru a vypadne z této smyčky.

Takže ovládání jde přímo z (*) na alert('Done!') .

Můžeme také přesunout popisek na samostatný řádek:

outer:
for (let i = 0; i < 3; i++) { ... }

continue direktivu lze také použít se štítkem. V tomto případě spuštění kódu přeskočí na další iteraci označené smyčky.

Štítky neumožňují nikam „skákat“.

Štítky nám neumožňují skočit na libovolné místo v kódu.

Není například možné provést toto:

break label; // jump to the label below (doesn't work)

label: for (...)

A break direktiva musí být uvnitř bloku kódu. Technicky postačí jakýkoli označený blok kódu, např.:

label: {
 // ...
 break label; // works
 // ...
}

…Přestože v 99,9 % případů break se používá uvnitř smyček, jak jsme viděli ve výše uvedených příkladech.

A continue je možné pouze zevnitř smyčky.

Shrnutí

Pokryli jsme 3 typy smyček:

  • while – Podmínka se kontroluje před každou iterací.
  • do..while – Podmínka se kontroluje po každé iteraci.
  • for (;;) – Podmínka se kontroluje před každou iterací, k dispozici jsou další nastavení.

Chcete-li vytvořit „nekonečnou“ smyčku, obvykle while(true) používá se konstrukt. Takovou smyčku, stejně jako kteroukoli jinou, lze zastavit pomocí break směrnice.

Pokud v aktuální iteraci nechceme nic dělat a chtěli bychom přesměrovat na další, můžeme použít continue směrnice.

break/continue podpůrné štítky před smyčkou. Štítek je jediný způsob pro break/continue uniknout z vnořené smyčky a přejít do vnější smyčky.