Obsahuje tyto položky:
- Pole
- Objekty
- Metody
- Funkce
- Podmínky
- Cykly
- Skoky
- Model DOM
- Události
- Propojení JS, CSS a HTML
- Setters & getters
- Datum
Zjistit funkcionalitu v prohlížeči: caniuse.com
Kam s tím?
Samostatný soubor
<!DOCTYPE html>
<html lang=“cs“ dir=“ltr“>
<head>
<meta charset=“utf-8“ />
<title>Kód v externím souboru</title>
<script src=“myScript.js“></script>
</head>
<body>
</body>
</html>
Odkaz na soubor může být buď v head, nebo body (viz níže).
Uvnitř HTML
Když prohlížeč načítá dokument HTML, převádí jeho značky na svou interní reprezentaci - DOM (objektový model dokumentu). My potom prostřednictvím JS kódu pracujeme s naší stránkou HTML prostřednictvím manipulace s modelem DOM.
Musíme však být opatrní – snaha o přístup do určité části modelu DOM dříve, než ji webový prohlížeč stihne sestavit, vede k chybám. Jestliže vložíme element script do záhlaví dokumentu HTML (do elementu head ), náš zdrojový kód se spustí okamžitě, a to právě v okamžiku, kdy ještě není sestavený model DOM. S tímto problémem se lze vypořádat dvěma způsoby. Můžeme buď zabalit náš kód do volání funkce window.onload() - viz konec kapitoly Události, kterou prohlížeč spouští, až sestaví model DOM, nebo můžeme element/y script vložit na konec elementu body, těsně před koncovou značku </body> . Tato varianta se potom rychleji zobrazuje.
Výpis na obrazovku
Zobrazení výstražné zprávy (je FUNKCE, nebo spíše uváděno jako METODA v rámci OBJEKTU Windows).
Umožní nám zobrazit text, nebo vypsat opsah proměnné (jméno, které uchovává informaci).
Píše se do <Script></Script>
Syntax: alert("Hello\nHow are you?");
(\n odsadí řádek)
- alert - informační okno jen s tlačítkem "OK"
- confirm - totéž ale navíc tlačítko "Storno"
- prompt - totéž co confirm, navíc textové pole
Pro testovací účely se používá výpis do konzole: console.log("text");
Komentáře v kódu
// toto je řádkový komentář
/* Toto je blokový
komentář. */
Pole
Syntax: var myArray = [1, "jablko", undefined, null, [] ];
Zápisu do hranatých závorek se říká "literál pole"
Literál vyjadřuje přímý zápis hodnoty (na rozdíl od např. proměnné), ale může znamenat i vstupní řetězec konečného automatu, nebo obecně označovat všechny lexikální symboly.
Indexové pole (index=pořadí prvku):
(Počítá se od nuly.)
var myArray = [];
myArray[0] = "Ahoj";
myArray[1] = "světe";
Asociativní pole:
(Nepoužívá se, lepší je využít OBJEKTY.)
var myArray = [];
myArray[„ovoce“] = "jablko";
myArray[„vozidlo“] = "traktor";
Pole se dají vnořovat:
var myArray = [poleNulaPrvni, poleNulaDruhe, [poleJednaPrvni, poleJednaDruhe]];
nactiPole = myArray[1]; //vrací "poleNulaDruhe"
nactiPole = myArray[2][1]; //vrací "poleJednaDruhe"
Metody s poli:
Syntax: nazevPole.metoda(doplňujíci_parametry);
Co jsou METODY?
Modifikační metody:
- push - přidání prvku na konec, vrací nový počet prvků (číslo)
- pop - koncový (poslední) smaže a zároveň vrátí
- shift - smaže první a vrátí ho
- unshift - přidá na začátek (i více), vrátí nový počet prvků (číslo)
- reverse - převrátí pořadí prvků
- sort - abecedně seřadí (čísla jako String)
- splice - můžeme do pole současně přidávat a odebírat z něj prvky
- myArray.splice(indexovePoradi, kolik, prvek1, ..., prvekN);
- indexovePoradi - jdi na index číslo; kolik - kolik prvků smaže; prvek1, -, prvekN - přidej nové prvky
- myArray.splice(indexovePoradi, kolik, prvek1, ..., prvekN);
Přístupové metody:
- concat -
pole4 = pole1.concat(pole2, pole3);
vytvoří nové pole (vrací ho) a do něj vloží obsah polí 1-3 - join -
alert("Čísla pole: " + cisla.join(", "));
sloučí prvky pole do jednoho řetězce String, do závorky můžeme dát, jak se oddělí (standardně čárkou) - slice - vytváří a vrací kopii vybrané oblasti
myArray.slice(2);
- počínaje prvkem 2 až do koncemyArray.slice(-2);
- počítá od konce, vrací poslední dva prvkymyArray.slice(2, 4);
- od prvku 2 po 4
- indexOf -
myArray.indexOf ("m", 4);
vrátí index prvku (číslo) na kterém se nachází "m", začne pátým prvkem (za čtyřkou). - lastIndexOf - stejné, jako výše, ale počítá od konce
Iterační metody (souvisí s CYKLY)
Přehled:
- forEach - prováděj s každým prvkem
- map - stejné, ale vrací konečný výsledek (celé pole)
- every - stejné jako výše, ale ověřuje platnost - výsledkem je TRUE, když jsou všechny hodnoty v poli platné
- some - stejné, ale ověřuje, jestli je alespoň jeden prvek platný
- filter - vyfiltruje prvky pole, které odpovídají kritériím a uloží je do nové proměnné
- reduce - matematické operace nad prvky pole (např. součet).
- reduceRight - stejné, ale začíná od konce
Příklady:
var pole, soucet;
pole = [4, 8, 15, 16, 23, 42];
soucet = 0;
pole.forEach(function(prvek) {soucet = soucet + prvek;});
alert("Součet činí: " + soucet);
Metodě forEach
předáváme anonymní FUNKCI, která přijímá jako parametr postupně hodnotu každého prvku a tu ukládá do proměnné "prvek" a následně provádí operace zadané v { } . Nebo jinak řečeno: postupně pro každý prvek pole se volá anonymní funkce. Funkcím předáváme parametry (hodnoty se kterými má pracovat). Parametrem je v tomto případě proměnná "prvek", kterou tímto automaticky deklarujeme a zároveň jí přiřazujeme hodnoty - postupně prvky pole.
POZOR: středník ukončuje každé přiřazení - i vnořené, viz výše: {soucet = soucet + prvek;}
var pole = [1, 2, 3, 4, 5];
var umocnene;
umocnene = pole.map(function(prvek) {return (prvek * prvek);});
Pole "umocnene" obsahuje [1, 4, 9, 16, 25].
var pole, jePlatne;
pole = [1, 2, 3, 4, 5];
jePlatne = pole.every(function(prvek) {return (prvek < 10);});
var pole, filtrovane;
pole = [1, 2, 3, 4, 5, 6, 7, 8, 9];
filtrovane = pole.filter(function(prvek) {return (prvek < 5);});
Součet prvků pole:
Prochází prvky pole a předává anonymní funkci jako argumenty aktuální hodnotu prvku a buď předchozího prvku (u prvních dvou), nebo hodnotu spočítanou v předchozím kroku (u třetího prvku). Začíná tím pádem u 1. kroku (počítáno od 0).
var pole, soucet;
pole = [1, 2, 3, 4, 5];
soucet = pole.reduce(function(predchozi, aktualni) {return predchozi + aktualni;});
Objekty
Pole se skvěle hodí pro ukládání číselné sekvence, kdežto objekt je vhodný pro ukládání dvojic: klíč : hodnota (property/name: value).
Syntax:
var mujObjekt = {klic_1:hodnota_1, klic_2:hodnota_2};
Zápisu do složených závorek se říká "literál objektu"
Existuje ještě konstruktor objektu, který se používá při vytváření instancí tříd, viz zde.
Syntax: var mujObjekt = Objekt();
// do proměnné mujObjekt vložíme právě vytvořený objekt s názvem Objekt
Přidávání hodnot do objektu
Závorkový zápis:
var mujObjekt = {};
mujObjekt["krestniJmeno“] = "Franta";
mujObjekt["prijmeni“] = "Vomáčka";
Mezi hranaté závorky můžeme zapisovat název proměnné, zatímco za tečku nikoliv. Závorkový zápis rovněž podporuje textové řetězce, které obsahují mezery a jiné zvláštní znaky, kdežto tečkový zápis to neumožňuje.
Tečkový zápis:
var mujObjekt = {};
mujObjekt.krestniJmeno = "Franta“;
mujObjekt.prijmeni = "Vomáčka“;
Tečkový zápis je jednodušší a obvyklejší.
Můžeme vytvořit objekt a zároveň do něj vložit hodnoty:
var auto = {vyrobce:"Škoda", typ:"Superb", barva:"modrá"};
Načítání z objektu
alert("Jmenuji se " + mujObjekt.krestniJmeno);
Na rozdíl od polí nemůžeme načítat data z objektu prostřednictvím číselného pořadí. U objektů lze používat pouze jmenný index:
var obj = {};
obj.krestniJmeno = „Franta“;
obj[0]; // vrací undefined
obj[„krestniJmeno“]; // vrací „Franta“
obj.krestniJmeno; // vrací „Franta“
Vnořování objektů a vytváření "Jmenných prostorů"
var automotocyklo = {
auto: {},
moto: {
enduro: {honda:"Africa-twin", yamaha:"Ténéré"},
naked: {honda:"Hornet", yamaha:"MT"}
},
cyklo: {}
};
automotocyklo.moto.enduro.honda; // vrací "Africa-twin“
automotocyklo.moto.naked.yamaha; // vrací „MT“
Jde přidávat i dodatečně:
automotocyklo.auto.skoda = "Superb";
automotocyklo.cyklo.vyrobce = "Author";
U jmenných prostorů je třeba kontrolovat, jestli náhodou už není objekt deklarovaný (abychom ho nepřepsali):
var automotocyklo.cyklo = automotocyklo.cyklo|| {};
Prostřednictvím operátoru OR ( || ) kontrolujeme, zda už je objekt definovaný. Když už existuje, přiřazujeme ho sobě samému, takže se
nic nezmění. Pokud neexistuje, ukládáme do proměnné "cyklo" výraz vpravo od operátoru ||. Tzn. uděláme z "cyklo" objekt, do kterého vložíme vnořený objekt "vyrobce":
automotocyklo.cyklo.vyrobce = {};
Metody
Metody jsou činnosti, akce, které se dají provádět s objekty, poli, ...
Syntax: objectName.methodName();, arrayName.methodName();
Metody mohou být:
- přístupové - přistupují k obsahu (get, join, toString, ...)
- modifikační - mění obsah (set, push, ...)
- iterační - opakují pro každý prvek (forEach, ..)
Hledání:
Includes (funguje pro: array, string)
vCemHledat.includes("coHledám");
Vrací true/false, pokud najde/nenajde.
IndexOf (array, string)
vCemHledat.indexOf("coHledám");
Vrací pozici indexu. Více v kapitole Pole.
Search (string)
vCemHledat.search("coHledám");
Vrací pozici, pokud nenajde, pak -1.
Match (string)
vCemHledat.search("coHledám");
Vrací, co hledáme jako objekt.
Test
RegExp.test(vCemHledat);
RegExp = (nutné ???) použití regulérních výrazů a metaznaků. Ty se oddělují rourou "|".
Vrací true/false.
Find (array)
Samo o sobě hledat neumí - vyžaduje k sobě funkci.
vCemHledat.find(jmenoFunkce);
Metoda zavolá funkci (např: function jmenoFunkce(vek) {return vek >= 18;} ) a zároveň ji automaticky jako parametr (vek) předá postupně všechny hodnoty pole (vCemHledat) - funkce se provede (zjistí, která hodnota je rovna nebo větší než 18) s každou hodnotou pole a vrátí ji.
Funkce
Funkce je seskupení (za konkrétním účelem) několika řádků kódu, které pojmenujeme. Funkce obalují skupinu operací. Celé seskupení potom voláme jménem.
Např. operaci a+b pojmenujeme "sčítání" a potom už jen voláme funkci "sčítání" (nepíšeme a+b).
Funkce se dají zapsat do souboru a volat z vnějšku. Takový soubor se nazývá knihovna (library), někdy modul či jednotka (unit).
Rozdíl funkce x procedura
Podobné funkcím jsou procedury.
Funkce jsou v podstatě oddělené od hlavního programu. Funkci zadáme argumenty, ta si je "přivlastní" jako vstupní parametry, zpracuje a vrátí do hlavního programu svůj výstup.
Procedury jen vykonají, co mají a do hlavního programu nic nepředávají.
Tohle je v podstatě procedura:
Vytvoříme funkci, která se provede. Její výstup nikam neukládáme, nepředáváme.
function myFunction() {alert("Ahoj");} // nemá žádné parametry
Zavoláme funkci jejím jménem, nepředávání jí žádné hodnoty.
myFunction() // nepředáváme žádné argumenty
Syntax:
Deklarujeme proměnnou "x". Přiřadíme jí (zavoláme) výstup z funkce "myFunction", té předáme hodnoty se kterými má pracovat (argumenty 4, 3).
var x;
x = myFunction(4, 3); // 4,3 jsou argumenty
alert(x);
function myFunction(a, b) {return a * b;} // a, b jsou parametry
Deklarujeme funkci se jménem "myFunction", která má v hlavičce parametry a, b (těm se přiřadí argumenty 4 a 3) a v těle {co se má udělat}. Parametry jsou jakoby proměnné, které se použijí uvnitř funkce. Parametrům se automaticky přiřadí argumenty.
Syntax ještě jednou a jednodušeji:
function myFunction(zprava) {alert(zprava);}
Vytvořím a pojmenuji funkci, do její proměnné "zpráva" uložím později při volání pozdrav, {funkce se provede (zobrazí obsah proměnné "zpráva"}.
myFunction("Posílám pozdrav");
Zavolám vytvořenou funkci a předám jí pozdrav.
Jak zjistíme, jestli určitá funkce (metoda) existují?
function testovaciFunkce() {
return false;
}
if (testovaciFunkce()) {alert("se závorkami");}
if (testovaciFunkce) {alert("bez závorek");}
Když v podmínce zavolám funkci se závorkami, řeší se její návratová hodnota. Ta je false, podmínka (testovaciFunkce = true) není splněna, zpráva se nezobrazí.
V druhém případě (bez závorek - neřeší se tedy návratová hodnota=co je ve funkci)) testujeme pouze, jestli daná funkce existuje. Ta existuje, takže se zobrazí zpráva.
Každá funkce (spíše "její objekt") má (automaticky) hodnotu length. Tou zjistíme, kolik argumentů funkce očekává.
function maFunkce(jedna, dva) {
}
alert(maFunkce.length);
Globální a lokální proměnné (neboli oblasti platnosti = scope)
Lokální proměnné jsou takové, které vzniknou uvnitř funkce a dají se použít jen tam:
function cau() {var ahoj = „ahoj“;}
Vnořené funkce mohou použít proměnné deklarované v rodičovské funkci:
function celeJmeno() { // vytvoření rodičovské funkce
var jmeno = "Evžen"; // deklarace lokální proměnné
function jmenoPrijmeni() { // vytvoření vnořené funkce
var prijmeni = "Vomáčka"; // deklarace lokální proměnné ve vnořené funkci (součást těla vnořené funkce)
alert("Celé jméno: " + jmeno + " " + prijmeni); // zobraz jméno i příjmení (ale až se funkce zavolá)
} // (ukončení těla vnořené funkce)
jmenoPrijmeni(); // volání vnořené funkce (součást těla rodičovské funkce)
} // ukončení těla rodičovské funkce
celeJmeno(); // volání rodičovské funkce
Funkce má ve skutečnosti přístup ke všem proměnným, které deklarujeme nad ní.
V první úrovni jsou Globální proměnné. Zde se teprve funkce vytváří. Proměnné zde vytvořené se dají použít ve všech vnořených funkcích.
Zdvihání proměnných
Je akce kterou dělá interpret jazyka JS automaticky na pozadí. Přesouvá deklarace proměnných na začátek funkce. Ale pouze deklarace, ne přiřazování hodnot.
Tzn., tohle bude fungovat, protože se řádek var jmeno;
přesune nahoru hned pod deklarování funkce:
function myFunction() {
jmeno = "Franta";
alert (jmeno);
var jmeno;
}
Ale tohle vrátí "undefined", protože je na konci i přiřazení hodnoty. Na začátek se přesune pouze deklarace, ne přiřazení:
function myFunction() {
alert (jmeno);
var jmeno = "Franta";
}
Způsoby vytvoření funkce
Jsou tři způsoby:
- deklarace
- výraz
- konstruktor
Konstruktor je metoda/funkce, která vytváří (jiný způsob tvorby je literál pole, objektu) objekt, pole, nebo funkci.
Konstruktor se používá málo, protože je náchylný na chyby a představuje bezpečnostní riziko. Význam ale má při tvorbě instancí tříd.
ad 1. DEKLARACE funkce
V tomto případě funkce musí mít jméno.
function myFunction() {
alert(„Ahoj“);
}
ad 2. VÝRAZ funkce
Funkce nemá jméno (proměnnné "pozdrav" přiřadíme anonymní funkci) , proto jí také říkáme anonymní funkce.
var pozdrav = function() {
alert(„Ahoj“);
}
POZOR i u funkcí platí zdvihání proměnných, takže:
alert(myFunction());
function myFunction() {
return "Ahoj!";
}
funguje jen proto, že si JS přesune deklaraci funkce nad funkci alert. Jen proto ji alert zná.
Ale u "Výrazu funkce" toto nefunguje, protože JS si přesune (zdvihne) jen deklaraci proměnné, ale ještě neví, že jí byla přiřazena nějaká funkce:
alert(cau());
var cau = function() {
return "Čau!";
};
Tohle už fungovat bude:
var cau = function() {
return "Čau!";
};
alert(cau());
DOPORUČENÍ :
Deklarace funkcí vždy zapisovat na začátek oblasti platnost (scope)i. Stejně tak u výrazů funkcí deklarovat proměnné, do kterých se budou tyto funkce ukládat, rovněž
na začátek oblasti platnosti.
U deklarace funkcí se mohou podmínky chovat nekonzistentně (platí stále?), lepší je použít Výraz funkce.
Příklad dle doporučení:
var pozdrav;
if (true) {
pozdrav = function() {
alert("Čau!");
}
} else {
pozdrav = function() {
alert("Ahoj!");
}
}
pozdrav();
Jak předat funkci jako parametr celé pole? Pomocí zápisu "Spread"
var pole = [3, 5 , 1];
alert(Math.max(pole)); // nebude fungovat - název pole předat nejde
alert(Math.max(...pole)); // tento zápis bude fungovat - Spread rozšíří obsah pole mezi parametry funkce
Řetěz prototypů a instance tříd
JS nepoužívá třídy (viz článek Programování obecně). Každá funkce se ale může chovat jako třída. Jestli jde o běžnou funkci, nebo třídu poznáme podle toho, že funkce jako třída má velké počáteční písmeno v názvu. Objekty (instance tříd) dědí vlastnosti a metody od jiných objektů (funkcí), ne od tříd. Instance tříd se vytváří pomocí konstruktoru objektu.
Každý objekt má svůj prototyp. Prototyp je objekt, ze kterého jiné objekty dědí vlastnosti:
var ford, mercedes;
function Auto() { // tělo funkce=objekt se stává prototypem - předpisem pro budoucí instance:
this.typ = "osobní",
this.výkon = "220 kW",
this.barva = "modrá"
};
ford = new Auto;
mercedes = new Auto;
alert(ford.typ);
Vytvoříme funkci "Auto" a v ní vnořený objekt (třídu = prototyp). Nové instance třídy - objekty "ford" a "mercedes" zdědí po prototypu vlastnosti "typ", "výkon", "barva". Nové instance zdědí po funkci-třídě "Auto" její objekt (prototyp).
Každá nově vytvořená instance bude mít stejné vlastnosti, ale ty mohou nabývat různých hodnot.
var bezny, sporici;
function Ucet(cislo) {
this.cisloUctu = cislo;
this.zustatek = 0;
this.vloz = function(castka) {
if (castka === Number(castka)) {
this.zustatek += castka;
}
};
this.vratZustatek = function() {return this.zustatek; };
}
bezny = new Ucet("12345678");
bezny.vloz(13.25);
bezny.vloz(4.69);
bezny.vloz(89.21);
sporici = new Ucet("87654321");
sporici.vloz(352.65);
alert(bezny.vratZustatek()); // vypisuje 107,15
alert(sporici.vratZustatek()); // vypisuje 352,65
Vytvořime funkci "Ucet" která bude pracovat s proměnnou (parametrem) "cislo". Posláním této funkce bude vytvořit třídu - předpis pro později vytvořené instance (vytvořené objekty pomocí new) této třídy "bezny" a "sporici". Náplní funkce bude v podstatě deklarovat objekt (pomocí klíčového slova this - odkazuje na vlastníka, v tomto případě funkci "Ucet") s vlastnostmi "cisloUctu", "zustatek" a metodami "vloz" a "vratZustatek".
Vytvoření instance třídy: proměnné "bezny" přiřadíme právě nově vytvořený objekt "Ucet" včetně vstupních dat (argumenty). Protože už ale existuje funkce (třída) se stejným jménem "Ucet" zdědí po ní vlastnosti a metody. Proměnná "bezny" se tak stane instancí třídy "Ucet".
DŮLEŽITÉ je, že klíčové slovo this se nyní odkazuje na instance. Takže vlastnosti a metody třídy "Ucet" patří výhradně těmto objektům (instancím). Proto můžeme/musíme volat "bezny.vratZustatek" a ne "Ucet.vratZustatek".
Následně můžeme zavolat instanci "bezny" a její zděděnou metodu "vloz" a předat jí data jako argumenty, které se přiřadí proměnné "castka" anonymní funkce, jejíž úkolem je data přičíst do proměnné "zustatek".
Ačkoli můžeme data vkládat a číst přímo: např. "bezny.zustatek = 500;" , nebo "alert(bezny.zustatek);", je lepší používat k tomu určené metody "bezny.vloz(500);"
Konstruktor
Když pracujeme s objektem, který je instancí nějaké funkce, můžeme chtít zjistit, z jaké funkce vznikl. Kromě toho můžeme také ze stejné funkce vytvořit další instanci.
var karel, franta, otakar;
function Karel() {
this.prvni = "Karel";
}
karel = new Karel();
karel.první; // vrací "Karel"
franta = new Karel();
franta.prvni; // vrací "Karel" // instance franta zdědila vlastnost prvni s hodnotou "Karel"
franta.prvni = "Franta"; // instance si přepíše svoji vlastnost prvni hodnotou "Franta"
franta.prvni; // nyní vrací "Franta"
otakar = new franta.constructor(); // vytvoříme novou instanci tak, že zavoláme konstruktor, který vytvořil objekt (instanci) franta a na jeho základě vytvoříme instanci otakar
otakar.prvni; // vrací "Franta", protože otakar vlastnost zdědil a ještě jí nepřiřadil vlastní hodnotu.
Metoda apply()
Umí změnit objekt, na který se odkazuje klíčové slovo this uvnitř funkce. Předáme jí takový objekt jako první argument:
var osoba, prijmeni;
prijmeni = "Vomáčka";
osoba = function() {
alert(this.prijmeni);
};
osoba(); // vrací "Vomáčka"
osoba.apply({prijmeni: "Žaloudek"}); // vrací "Žaloudek"
Nejdříve funkce neobsahuje žádný objekt, this se proto odkazuje na globální objekt Window, kam patří i proměnná prijmeni.
Potom funkci v proměnné osoba přiřadíme (nově vytvoříme) objekt s vlastností prijmeni a hodnotou "Žaloudek". Použili jsme k tomu metodu apply, které jsme nový objekt předali jako první argument.
Když voláme metodu apply() , můžeme jí také předat seznam argumentů pro volanou funkci:
var osoba;
osoba = function(krestni, prijmeni, vek) {
alert(krestni + " " + prijmeni + ", " + vek);
}
osoba.apply(null, ["Evžen", "Vomáčka", 43]);
Jako první argument nepředáváme žádný objekt, proto null. Jako druhý argument předáme pole s hodnotami.
Stejně funguje metoda call(), jen má jiný zápis:
osoba.call(null, "Evžen", "Vomáčka", 43);
Metoda bind()
Metodu bind můžeme volat na funkci, které chceme předat objekt, na nějž bude odkazovat klíčové slovo this. Stejně jako metoda apply. Metoda bind ale vytváří novou funkci na kterou je tento objekt navázaný.
var franta, osoba, jmena;
osoba = function() {
return this.prijmeni;
};
franta = osoba.bind({prijmeni: "Vopršálek"});
alert(franta()); // vrací "Vopršálek"
jmena = {
prijmeni: "Žaloudek",
franta: franta,
osoba: osoba
};
jmena.franta(); // vrací "Vopršálek"
jmena.osoba(); // vrací "Žaloudek"
Cykly
Použijeme když chceme opakovat nějaký blok kódu, dokud platí určitá podmínka.
while
while (podmínka) {
příkazy
}
Jako podmínku můžeme použít jakýkoliv výraz, který lze vyhodnotit jako pravdivostní hodnotu true nebo false. Část s příkazy tvoří kód, který se provede, pokud bude daná podmínka pravdivá.
Příklad
var zbyvajiciUkoly = 3;
while (zbyvajiciUkoly > 0) {
alert("Zbývá vám dokončit úkolů: " + zbyvajiciUkoly);
zbyvajiciUkoly--;
}
Pokud zapíšeme stejný příklad jinak, zacyklí se a nikdy neskončí:
function vratDalsi(cislo) {
alert(cislo++);
}
var i = 0;
while (i < 3) {
i = vratDalsi(i);
}
- Do i se zapíše 0.
- Potom se vyhodnotí podmínka. Dokud je i < 3 volá se funkce vratDalsi s argumentem “i”. Jejím úkolem je zobrazit výstražné okno, které vrátí “číslo” (tedy “i”). Potom se “i” zvýší o 1.
- Díky i=vratDalsi(i); se výstup z funkce (tedy “cislo ++”) zapíše do “i”. Problém je, že ++ nejdříve vrací, potom navyšuje. Proto bude “i“ neustále rovno nule a kód nikdy neskončí.
POZOR !
Operandy ++ / - - nejdříve vrátí hodnotu, potom teprve zvýší, nebo sníží hodnotu o 1.
do while
Na rozdíl od cyklu while se provede vždy alespoň jedenkrát.
do {
alert("Toto se vypíše alespoň jednou.");
} while (false);
Příkad použití:
var zbyvajiciUkoly = 3;
do {
alert("Zbývá vám dokončit úkolů: " + zbyvajiciUkoly);
zbyvajiciUkoly--;
} while (zbyvajiciUkoly > 0);
for
Pomocí tohoto příkazu spouštíme blok kódu po určitý počet opakování. V inicializační části deklarujeme proměnnou a přiřadíme jí hodnotu (i=0). Je lepší uvést klíčové slovo "var". Když to neuděláme, bude mít proměnná globální charakter a může potom kolidovat s jinými a dělat problémy. Na konečný výraz se dostane až úplně na závěr poté, co se provedou příkazy.
for (inicializace; podmínka; konečný výraz) {
příkazy
}
V cyklu můžeme používat také více operátorů, např i < 10 && i % 2 === 0 (kontroluje, zda je i menší než 10 a zároveň dělitelné 2), nebo více výrazů (var i = 0, j = 0; i < 3; i++, j+=2), a nebo můžeme použít matematické funkce:
for (var i = 0; i < 0.9; i = Math.random()) {
alert(i);
}
Dokud bude i < 0,9 generují se náhodná čísla. Cylus skončí, jakmile padne číslo 0,9 a větší.
for in
var data;
data = {
krestni: "Franta",
prijmeni: "Votipka",
vek: 40
};
for (var klic in data) {
alert(klic + "je " + data[klic]);
}
Funkce postupně prochází klíče objektu. Pro výpis hodnoty klíče použijeme závorkový zápis "data[klic]".
RADA: nepoužívat cyklus for in pro procházení polí, ale raději zvolit běžný cyklus for.
Skoky, funkce vyššího řádu a rekurze
Skokový příkaz přesouvá tok programu na jinou část kódu.
Příkazem break ukončujeme cyklus. Ale lze jej téměř vždy nahradit nějakou podmínkou cyklu. Zde ukončíme cyklus u čísla 3. K výpisu číla 3 se už nedostane:
var text = "";
var i;
for (i = 0; i < 10; i++) {
if (i === 3) { break; }
text += "Jsme u čísla: " + i + "; ";
}
alert(text);
Pokud vyměníme break za continue, pak cyklus neukončíme, ale přecházíme k následujícímu průchodu cyklem. V cyklu for bychom přesunuli tok programu na spuštění konečného výrazu (tedy zvýšení i o 1) a až poté by došlo k dalšímu ověření podmínky v následujícím cyklu.
Pomocí příkazu return ukončujeme funkce a zároveň definujeme jejich návratovou hodnotu.
Metody, které přijímají funkce jako argumenty, jsou funkce vyššího řádu.
Zde příklad, který využívá metody polí:
var maCisla = [3, 5, 10, 4, 2, 1, 16, 7];
var soucet = maCisla.filter(function(x) {return x % 2 === 0;})
.reduce(function(cislo1, cislo2) {return cislo1 + cislo2;});
alert(soucet);
Nejdříve vyfiltrujeme čísla dělitelná 2 (vytvoří se nové pole), potom pracujeme s prvky nového pole tak, že je sečteme.
Další příklad funkcí vyššího řádu:
var ukoly = [
{text: "Nakoupit", resitel: "Petr"},
{text: "Uvařit", resitel: "Petr"},
{text: "Zaplatit", resitel: "Petr"},
{text: "Opravit", resitel: "Pavel"}
];
function spocitejResitele(ukoly, jmeno) {
return ukoly.filter(function(ukol) {
return ukol.resitel === jmeno;
}).length;
}
Rekurze
Rekurze se dobře předvádí na výpočtu faktoriálu. Ten bychom vypočítali za pomoci cyklů následovně:
function faktorial(cislo) {
var vysledek = 1;
for (var i = cislo; i > 0; i--) {vysledek *= i;}
alert(vysledek);
}
faktorial(5)
Pomocí rekurze by stejný výpočet vypadal takto:
function faktorial(cislo) {
if (1 === cislo) {
return cislo;
} else {
return cislo * faktorial(cislo - 1);
}
}
alert(faktorial(5));
Funkce na řádku return cislo * faktorial(cislo - 1);
volá samu sebe, jen je vstupní argument o 1 menší.
Takže když vypíšeme průběh bude zde return 5*4*3*2*return 1(tím vyhoví první podmínka, return ji ukončí a vrátí 1, vše se vynásobí a vrátí výsledek).
Model DOM
Když prohlížeč načítá dokument HTML, převádí jeho značky na svou interní reprezentaci - DOM (objektový model dokumentu). My potom prostřednictvím JS kódu pracujeme s naší stránkou HTML prostřednictvím manipulace s modelem DOM.
Nejvýše v hierarchii je objekt dokument
. Slouží jako vstupní bod pro celý náš dokument. Všechny další objekty, metody a v vlastnosti vychází z tohoto objektu. Např. titulek dokumentu načteme pomocí document.title
.
Když načteme element do proměnné, chová se jako pole a můžeme ho např. postupně procházet:
var obrazky, obrazek;
obrazky = document.images;
for (var i = 0; i < obrazky.length; i++) {
obrazek = obrazky[i]; // získáme odkaz na element img
console.log(obrazek);
}
V DOM Level1 byly zavedeny uzly - virtuální objekty DOM. "Node" je hlavní uzel - objekt a z něj vycházejí další uzly - objekty DOM: Documet (je kořenem stromového modelu DOM), Element, Attr, Text.
var mujOdkaz = document.createElement("a");
Vytvoří uzel elementu. Ten ale neexistuje, je pouze v paměti, není součástí daného dokumentu. Je to v podstatě jen odkaz na element uložený v proměnné. Musíme ho ještě připojit k některému současnému uzlu modelu DOM - prostřednictvím metody appendChild(). Přiřadíme ho tedy jako potomek k elementu body:
document.body.appendChild(mujOdkaz);
Můžeme také přidat atribut:
mujOdkaz.setAttribute("href", "http://www.w3c.org/");
Chceme-li zjistit, zda má element nějaké atributy, zavoláme metodu hasAttributes() (vrací false, true). Pokud se zeptáme hasAttributes("id"), ptáme se na konkrétní atribut, v tomto případě id (jestli je součástí elementu).
nebo vytvořit celý uzel-atribut i s hodnotou (samotným odkazem na web):
var mujOdkaz = document.createElement("a");
document.body.appendChild(mujOdkaz);
var href;
href = document.createAttribute("href");
href.nodeValue = "http://www.w3c.org/"; // pokud bychom chtěli dodatečně zjistit hodnotu atributu, můžeme zavolat metodu getAttribute()
mujOdkaz.setAttributeNode(href);
Nejdříve jsme vytvořili uzel pomocí createAttribute() a potom jsme ho přiřadili k elementu pomocí setAttribute().
Dále můžeme elementu přidat textový uzel:
var t = document.createTextNode("W3C");
mujOdkaz.appendChild(t);
Výsledek:
<!-- <a href="http://www.w3c.org">W3C</a>-->
"a" je uzel elementu - obal, který obsahuje i atributy "href" a samotný text "W3C. Atribut "href" je také uzel (typu Attr) a potomek uzlu "a". Atributy už nemohou mít potomky, stejně jako samotný text - jsou to koncové uzly (listy).
Události
Abychom mohli zpracovat událost, musíme odpovědět na několik otázek:
- O jakou akci se jedná? Např. o kliknutí myší.
- Na jaké části stránky tato akce nastala? Např. na tlačítku.
- Jak zpracujeme tuto akci? Např. zobrazíme výstražnou zprávu.
- Jak definujeme funkci, která zpracuje tuto akci?
To, že by měl nějaký element na stránce zpracovat určitou událost, sdělíme prohlížeči tak, že na daném elementu zaregistrujeme obsluhující funkci události.
Obsluhující funkce událostí můžeme registrovat třemi způsoby.
- JavaScriptový kód vložíme přímo do HTML kódu (ale už se nepoužívá)
- metoda addEventListener()
- obsluhující funkci nastavíme jako hodnotu vlastnosti elementu v modelu DOM, přičemž název vlastnosti začíná on a následuje název údálosti (např. onclick)
ad 1. přímý zápis do HTML
<button onclick="alert('Přímo v HTML')"> Klikni na mě!</button>
ad 2. metoda addEventListener() má tři parametry:
- type – typ události, které nasloucháme, např. click.
- listener – obsluhující funkce, v níž zpracováváme danou událost, např. vlastní funkce, ve které zobrazíme výstražnou zprávu
- useCapture – pokud má hodnotu true, směřuje v hierarchii dolů (view, document, HTML, body, element), když false (výchozí) směřuje k vyšším vrstvám.
<body>
<button id="klikniNaMe">Klikni na mě!</button>
<script>
var meTlacitko = document.getElementById("klikniNaMe");
function zpracujKliknuti() {alert("Kliknul jsi na tlačítko!");}
meTlacitko.addEventListener("click", zpracujKliknuti, false);
</script>
</body>
ad 3. vlastnosti onclick přidělíme hodnotu tímto způsobem:
<button id="klikniNaMe">Klikni na mě!</button>
<script>
var meTlacitko = document.getElementById("klikniNaMe");
meTlacitko.onclick = function(e) {alert("Kliknul jsi na tlačítko!");}
</script>
Nejdříve se načte element a uloží do proměnné meTlacitko. Potom na tomto elementu registrujeme událost onclick, která se stane vlastností tohoto elementu. Vlastnosti elementu přidáme hodnotu, tou je funkce, která volá alert.
Parametr "e" v části function(e)
reprezentuje objekt události. V případě kliknutí objekt události obsahuje všechny vlastnosti kliknutí myši (např. souřadnice na kterých jsme klikli). Toho potom můžeme ve funkci využít (nechat si např. souřadnice vypsat).
Nastavit hodnotu vlastnosti je jednodušší, ale tímto zápisem můžeme s událostí (elementem) svázat pouze jedinou funkci. Kdežto metodu addEventListener() můžeme na jedinou událost volat vícekrát. Na jeden element a jeho událost můžeme použít více funkcí.
Událost bychom měli svazovat jen s elementy, které už mají pro tuto událost nějakou výchozí akci. Událost klepnutí bychom tudíž měli aplikovat kupříkladu na elementy "a" a "button".
Zápis JS kódu do <head>
Pro zápis kódu JS je důležitá událost "onload". Většinou musíme počkat, až se načte celá HTML stránka a potom teprve můžeme pomocí JS přistupovat k elementům. Máme-li <script> umístěn v <head>, pak jej zabalíme do obsluhující funkce pro událost: window.onload(). Ta zajístí, že se JS kód spustí až poté, co se stránka HTML celá načte.
Propojení JS, CSS a HTML
Jak pomocí JS měnit CSS
<style>
#myDIV {
width: 200px;
height: 200px;
background-color: lightblue;
}
</style>
<p>Click the "Try it" button to set the display property of the DIV element to "none":</p>
<button onclick="myFunction()">Try it</button>
<div id="myDIV">
This is my DIV element.
</div>
<script>
function myFunction() {
document.getElementById("myDIV").style.display = "none";
}
</script>
Zpracování formuláře pomocí JS
Setters & Getters
var person = {
firstName: "Franta",
lastName : "Vopršálek",
language : "NO",
set lang(hodnota) {
this.language = hodnota;
}
};
person.lang = "cs";
document.getElementById("demo").innerHTML = person.language;
var person = {
firstName: "Franta",
lastName : "Vopršálek",
language : "",
set lang(hodnota) {
this.language = hodnota.toUpperCase();
}
};
person.lang = "cs";
document.getElementById("demo").innerHTML = person.language;
var person = {
firstName: "Franta",
lastName : "Vopršálek",
get fullName() {
return this.firstName + " " + this.lastName;
}
};
document.getElementById("demo").innerHTML = person.fullName;
Datum
(Datum se ukládá v milisekundách od 1.1.1970. Využívá se čas prohlížeče.)
Syntax: Date()
Čas se zobrazí jako typ String.
Jednoduchý příklad.
Používá se spíše vytvoření objektu - syntax: new Date()
.
Ale zobrazí se stejně jako String - automaticky se provede metoda "toString()
"
Pokud bychom chtěli převést na číslo, pak: "Number()
"
K zobrazení různých informací z objektu použijeme METODY "get"var d = new Date();
document.getElementById("demo").innerHTML = d.getHours();
K zápisu našich požadavků do objektu použijeme METODY "set"var d = new Date();
d.setFullYear(2000);
document.getElementById("demo").innerHTML = d;
Výsledek: Fri Mar 27 2000 16:58:11 GMT+0100 (dnes je 27. března 2020)
Výsledek je stejný jako bysme použili:var d = new Date("2015-03-25"); //tímto "vnutíme" vlastní datum
document.getElementById("demo").innerHTML = d;
Výsledek: Wed Mar 25 2015 01:00:00 GMT+0100
Podmínky
Příklad (Pozdrav-jaká část dne?)