Cílem této učebnice základů programování v Javascriptu je naučit se dovednost pragmatického programování čili kodérství. Není přitom ani trochu záměr se učit programovat pěkně nebo efektivně, to si nechme na pozdější studium.

Projekt je čerstvě rozpracovaný od února 2021. Do května 2021 se jeho podoba trochu ustálí.

Cvičné úlohy editovat

Sada třiceti cvičných úloh je dostupná na septima.dominec.eu. Úlohy jsou dělené do tří sad se vzrůstající náročností:

  • úlohy 01-09 jsou vhodné pro osvojení úplných základů programování a pro pochopení, jak odevzdávat řešení,
  • úlohy 10-19 vyžadují přemýšlení, ale zadání a případné rady vedou přímo ke správnému řešení,
  • úlohy 20-30 jsou čistý freestyle, nicméně snad stále v mezích základní učebnice programování.

Samotný cvičný sandbox je psaný samozřejmě také v Javascriptu a je úplně v pořádku, pokud ho cokoliv z toho zdroje budete kopírovat, upravovat a používat pro jakékoliv účely.

Drobné rady editovat

Vytvoření pole s předem určeným obsahem editovat

var pole = [];
pole.push(1);
pole.push("b");
return pole;

...můžeme zapsat kratším způsobem:

return [1, "b"];

Cyklus for..of editovat

var vysledek = [];
for (var i = 0; i < arg.length; i++) {
  vysledek.push(2 * arg[i]);
}

Než abychom takhle procházeli čísla od 0 do arg.length - 1 a z nich pak vymýšleli arg[i], můžeme cyklem for...of projít přímo obsah pole:

var vysledek = [];
for (var x of arg) {
  vysledek.push(2 * x);
}

Funkce Array.map editovat

Pokračujeme v předchozím příkladu a ještě ho zjednodušíme:

var vysledek = arg.map(x => 2 * x)

Výraz x => 2 * x je ve skutečnosti sám o sobě funkce. Kdybychom nechtěli být až tak struční, můžeme si ho připravit předem, takže možná bude jasnější, co se vlastně děje:

function uprava(x) {
 return 2 * x;
}
var vysledek = arg.map(uprava);

Podobný zápis jsme už používali dřív ve volání funkce Array.sort((a, b) => a - b)

Rozbalení pole do proměnných editovat

Je to vlastně opačný postup než prve zmíněné vytvoření pole s určeným obsahem. Obsah pole si můžeme rozbalit do několika proměnných a pracovat s nimi samostatně. Šetří to práci:

var arg = [10, 20, 30];
// místo obyčejného čtení položek:
var a = arg[0];
var b = arg[1];
var c = arg[2];
// ...můžeme napsat jeden příkaz:
var [a, b, c, ...zbytek] = arg;

Rozbalení pole do funkce editovat

Chceme spustit nějakou funkci a parametry máme připravené v poli:

var parametry = [10, 20, 30];
function soucet(a, b, c) {
  return a + b + c;
}
// obyčejný postup:
soucet(parametry[0], parametry[1], parametry[2]);
// s pomocí tří teček jde totéž udělat snáz:
soucet(...parametry);

Zvlášť mazané je to v kombinaci s funkcí, která bere libovolný počet parametrů – například jako Math.max. Jedním výrazem pak můžeme najít největší číslo v poli: Math.max(...arg); Z výukového hlediska by bylo užitečnější použít cyklus, ale co už.

Nedefinovaná hodnota proměnné editovat

Hodnota undefined se dá použít v podmínkách, jenže při každém porovnání vrátí false. Dá se na to spolehnout:

var x;
x == 0;  // false
x < 0; // false
x > 0; // false
(x < 0) || (x >= 0) // false
Math.abs(x) >= x // false

Hodnota undefined se objeví sama, když sáhneme, kam nemáme. Prohlížeč nehodí chybu a i na to se dá spolehnout:

var x = [10, 20];
x[2] // undefined
x[-1] // undefined
x.whatever // undefined

Když budeme používat podobné triky, bude asi těžší pak ten kód přečíst a pochopit. Dokud ale řešíme jednoduché školní příklady, nemusí to vadit. Tak například, když chci najít maximum v poli čísel:

var nejvetsi;
for (var i=0; i<arg.length; i++) {
  if (arg[i] < nejvetsi) {
    // nedělám nic
  } else {
    nejvetsi = arg[i];
  }
}

Plytká řešení editovat

Jedna hodně obecná rada: počítač má ohromný výkon, tak ho nešetřete. Psát programy tak, aby běžely rychle, chce dost zkušeností, a selský rozum většinou spíš uškodí – byť v něm bude upřímné snahy, kolik chce. Pokud není nutné řešit podrobnosti, je lepší se jim vyhnout. Čím kratší program napíšete, tím jednodušší je v něm pak opravovat chyby.

Výjimečnosti editovat

Program jde zapsat na jeden řádek:

if (pocet == 0) {
  return "";
} else {
  return " ".repeat(pocet);
}

Řešení:

return " ".repeat(pocet);

Dva kroky editovat

Program rozdělte na dva kroky, které se provedou postupně. Je to trochu delší, ale snad jednodušší na pochopení a později se podle toho dá vytvořit opravdu šikovné řešení.

var vysledek = [];
for (var cislo of pole) {
  if (cislo > vysledek[0]) {
    vysledek = [cislo];
  } else if (cislo == vysledek[0]) {
    vysledek.push(cislo); // řádky 7 a 8 jsou už jen } }
  }
}

Řešení:

var maximum = 0;
for (var cislo of pole) {
  if (cislo > maximum) {
    maximum = cislo;
  }
}
var vysledek = [];
for (var cislo of pole) {
  if (cislo == maximum) {
    vysledek.push(cislo);
  }
}

Pak bychom mohli pokračovat tím, že první i druhý krok předchozího řešení naprogramujeme opravdu pěkně a efektivně:

var maximum = Math.max(...pole);
var vysledek = pole.filter(cislo => cislo == maximum);

Šikovné porovnávání editovat

Zjednodušte program. Může být užitečné nastudovat, jak se chová hodnota undefined.

if (a < b) {
  if (c < b) {
    return true;
  }
}
if (a < b) {
  if (c == undefined) {
    return true;
  }
}
if (a == undefined) {
  if (c < b) {
    return true;
  }
}
if (a == undefined) {
  if (c == undefined) {
    return true;
  }
}
return false;

V prvním kroku řešení spojíme první dvě podmínky dohromady:

if (a < b) {
  if (c < b) {
    return true;
  }
  if (c == undefined) {
    return true;
  }
}
if (a == undefined) {
  if (c < b) {
    return true;
  }
  if (c == undefined) {
    return true;
  }
}
return false;

Dále obrátíme nerovnosti pomocí vykřičníku (negace). Využíváme toho, že (c < b) dává pro čísla stejné výsledky jako !(c >= b)

if (a < b) {
  if (!(c >= b)) {
    return true;
  }
  if (c == undefined) {
    return true;
  }
}
if (a == undefined) {
  if (!(c >= b)) {
    return true;
  }
  if (c == undefined) {
    return true;
  }
}
return false;

Teď nám dojde, že podmínka !(c >= b) platí i když (c == undefined). Tu druhou podmínku už není potřeba psát.

if (a < b) {
  if (!(c >= b)) {
    return true;
  }
}
if (a == undefined) {
  if (!(c >= b)) {
    return true;
  }
}
return false;

Teď si všimneme, že stejný trik jde udělat i s (a < b).

if (!(a >= b)) {
  if (!(c >= b)) {
    return true;
  }
}
return false;

Pro řešení na jeden řádek se bude hodit spojka &&, čili „a zároveň“:

return (!(a >= b) && !(c >= b));

Takovéhle triky využívající undefined bývají riskantní, ale tentokrát se to vyplatilo.