Základy programovania
v JavaScripte
Milan Herda, 03/2020
Lekcia 7
Čo nás čaká
- opakovanie (objekt)
- objekt v praxi: ovládanie Karla pomocou tlačidiel
Typy premenných
Primitívne
- boolean
- číslo
- reťazec
- null
- undefined
Zložené
- objekt
- pole
- funkcia
Objekt
Typ zloženej premennej.
Môže obsahovať skupinu primitívnych
a/alebo zložených hodnôt.
Každej položke objektu hovoríme
vlastnosť
Ak je vlastnosť funkciou,
hovoríme jej
metóda
const prazdnyObjekt = {};
const fero = {
vek: 45,
vyska: 183,
adresa: {
ulica: 'Farská 42',
obec: 'Nitra',
},
zmenVek: function (novyVek) {
this.vek = vek;
},
};
Úloha:
Chceme na stránku pridať tlačidlá, pomocou ktorých budeme vedieť:
Chceme mať na stránke sekciu, v ktorej budeme zobrazovať, na ktorú svetovú stranu je Karel práve otočený.
Keď sa Karel otočí, info na stránke sa zmení.
- Karla otočiť doľava
- otočiť ho doprava
- pohnúť o jeden krok dopredu
Želaný stav
Algoritmizácia
Rozložíme problém na časti
- urobíme HTML markup pre tlačidlá
- urobíme HTML markup pre info o otočení
- spojazdníme tlačidlá
- rozhodneme sa, ako budeme uchovávať smer
- pri otočení musíme upraviť smer
- po každom otočení upravíme zobrazenú info o smere
Riešenie: HTML markup pre tlačidlá
<section class="section">
<div class="buttons has-addons">
<button class="button is-warning" id="btn-left">
Doľava
</button>
<button class="button is-success" id="btn-step">
Krok dopredu
</button>
<button class="button is-warning" id="btn-right">
Doprava
</button>
</div>
</section>
Riešenie: HTML markup pre info o otočení
<section class="section">
<!-- tlačidlá -->
<div class="level">
<div class="level-left">
<div class="level-item has-text-centered">
<div>
<p class="heading">Otočený na</p>
<p class="title" id="direction">sever</p>
</div>
</div>
</div>
</div>
</section>
Riešenie: spojazdníme tlačidlá
<script>
const btnStep = document.querySelector('#btn-step');
btnStep.addEventListener('click', function (event) {
if (!jePredTebouStena()) {
krokDopredu();
}
});
const btnLeft = document.querySelector('#btn-left');
btnLeft.addEventListener('click', function (event) {
otocDolava();
});
const btnRight = document.querySelector('#btn-right');
btnRight.addEventListener('click', function (event) {
otocDoprava();
});
</script>
Nechýba nám event.preventDefault()?
Tieto tlačidlá nie sú súčasťou formuláru a tak nemajú inú defaultnú akciu, ktorú by sme potrebovali zrušiť.
Nie.
"Rozhodneme sa, ako budeme uchovávať smer"
Smer, kam je Karel otočený, je vlastnosťou Karla.
Karel môže mať potenciálne viac vlastností (riadok, stĺpec...).
Karel bude objekt a smer bude jednou z jeho vlastností.
Riešenie: uchovávanie smeru
const SEVER = 'sever';
const JUH = 'juh';
const VYCHOD = 'východ';
const ZAPAD = 'západ';
const karel = {
smer: SEVER,
};
Ale veď to vyzerá, ako objekt karel z minulej lekcie.
Áno, nie je to náhoda :) Použijeme presne tento hotový objekt karel, aj s jeho metódami
Riešenie: po otočení upravíme smer
const btnLeft = document.querySelector('#btn-left');
btnLeft.addEventListener('click', function (event) {
otocDolava();
karel.smer = akyJeDalsiSmerVlavo(karel.smer);
});
const btnRight = document.querySelector('#btn-right');
btnRight.addEventListener('click', function (event) {
otocDoprava();
karel.smer = akyJeDalsiSmerVpravo(karel.smer);
});
- najskôr otočíme Karla
- potom upravíme Karlov smer
const btnLeft = document.querySelector('#btn-left');
btnLeft.addEventListener('click', function (event) {
otocDolava();
karel.vlavoVbok();
});
const btnRight = document.querySelector('#btn-right');
btnRight.addEventListener('click', function (event) {
otocDoprava();
karel.vpravoVbok();
});
Riešenie: po otočení upravíme smer
otocDolava();
karel.vlavoVbok();
- najskôr otočíme Karla
- potom upravíme Karlov smer
karel.vlavoVbok();
Riešenie: po otočení upravíme smer
const SEVER = 'sever';
const JUH = 'juh';
const VYCHOD = 'východ';
const ZAPAD = 'západ';
const karel = {
smer: SEVER,
vlavoVbok: function () {
otocDolava();
this.smer = akyJeDalsiSmerVlavo(this.smer);
},
vpravoVbok: function () {
otocDoprava();
this.smer = akyJeDalsiSmerVpravo(this.smer);
},
};
Riešenie: po otočení upravíme smer
const btnLeft = document.querySelector('#btn-left');
btnLeft.addEventListener('click', function () {
karel.vlavoVbok();
});
const btnRight = document.querySelector('#btn-right');
btnRight.addEventListener('click', function () {
karel.vpravoVbok();
});
Riešenie: po každom otočení upravíme zobrazenú info o smere
const infoDirection = document.querySelecter('#direction');
const btnLeft = document.querySelector('#btn-left');
btnLeft.addEventListener('click', function () {
karel.dolava();
infoDirection.innerHTML = karel.smer;
});
const btnRight = document.querySelector('#btn-right');
btnRight.addEventListener('click', function () {
karel.doprava();
infoDirection.innerHTML = karel.smer;
});
Má riešenie nedostatky?
- Kráčanie dopredu hýbe Karlom, takže by tiež malo byť súčasťou objektu karel.
Má riešenie nedostatky?
- Kráčanie dopredu hýbe Karlom, takže by tiež malo byť súčasťou objektu karel.
const btnStep = document.querySelector('#btn-step');
btnStep.addEventListener('click', function (event) {
karel.krok();
});
const karel = {
// ... zvyšný doterajsí kód ...
krok: function () {
if (!jePredTebouStena()) {
krokDopredu();
}
}
};
Má riešenie nedostatky?
Kráčanie dopredu hýbe Karlom, takže by tiež malo byť súčasťou objektu karel.- Vždy po zavolaní karel.vlavoVbok() musíme hneď písať aj príkaz pre úpravu informácie.
Ak zavoláme karel.vlavoVbok() a zabudneme druhý príkaz, tak sa nám rozíde zobrazená informácia s reálnym stavom
Riešenie: Karlovi povieme, že vždy po otočení chceme updatnúť zobrazené info
const karel = {
// ...
vlavoVbok: function () {
otocDolava();
this.smer = akyJeDalsiSmerVlavo(this.smer);
document.querySelecter('#direction').innerHTML = this.smer;
},
};
Takto je ale Karel pevne previazaný so stránkou, kde sa používa a vyžaduje, aby na tej stránke bol element #direction.
To nie je dobré, lebo nám to neumožňuje použiť Karla na inej stránke, kde taký element nie je.
Pokus o riešenie: parametrizácia
Hlavný problém je pevné previazanie Karla na element so selektorom "#direction"
Ak tento selektor nebude v Karlovi pevne uvedený, ale príde nejako zvonka, tak je problém vyriešený.
Pokus o riešenie: parametrizácia
const karel = {
// ...
vlavoVbok: function (selektor) {
otocDolava();
this.smer = akyJeDalsiSmerVlavo(this.smer);
document.querySelecter(selektor).innerHTML = this.smer;
},
};
Toto nie je dobré riešenie, lebo nás núti do každého zavolania karel.vlavoVbok() odovzdať selektor
karel.vlavoVbok('#direction');
Pokus o riešenie: parametrizácia cez property
const karel = {
// ...
selektorPreSmer: null,
vlavoVbok: function () {
otocDolava();
this.smer = akyJeDalsiSmerVlavo(this.smer);
document.querySelecter(this.selektorPreSmer).innerHTML = this.smer;
},
};
karel.selektorPreSmer = '#direction';
const btnLeft = document.querySelector('#btn-left');
btnLeft.addEventListener('click', function () {
karel.vlavoVbok();
});
Vznikol nám však duplicitný kód
const karel = {
// ...
selektorPreSmer: null,
vlavoVbok: function () {
otocDolava();
this.smer = akyJeDalsiSmerVlavo(this.smer);
// pridáme kontrolu, či bol selektor nastavený
if (this.selektorPreSmer !== null) {
document.querySelecter(this.selektorPreSmer).innerHTML = this.smer;
}
},
vpravoVbok: function () {
otocDoprava();
this.smer = akyJeDalsiSmerVpravo(this.smer);
// tu máme duplicitu
if (this.selektorPreSmer !== null) {
document.querySelecter(this.selektorPreSmer).innerHTML = this.smer;
}
},
};
Vytiahneme duplicitu do samostatnej metódy
const karel = {
// ...
selektorPreSmer: null,
dajVedietOZmeneSmeru: function () {
if (this.selektorPreSmer !== null) {
document.querySelecter(this.selektorPreSmer).innerHTML = this.smer;
}
},
vlavoVbok: function () {
otocDolava();
this.smer = akyJeDalsiSmerVlavo(this.smer);
this.dajVedietOZmeneZmeneSmeru();
},
vpravoVbok: function () {
otocDoprava();
this.smer = akyJeDalsiSmerVpravo(this.smer);
this.dajVedietOZmeneSmeru();
},
};
Bonus: Skúsme Karla úplne odtieniť od HTML
- nechcem, aby bol Karel naviazaný na použitie vo webstránke
- musím sa preto zbaviť volania document.querySelector
- Karel musí kódu, ktorý ho používa, ponúknuť možnosť, ako sa "zavesiť" na udalosť zmeny smeru
- jednoduchý spôsob je ponúknuť prázdnu metódu, ktorú vonkajší svet nastaví podľa svojej potreby
const karel = {
// ...
// Už nepotrebujeme selektor.
// Namiesto neho ponúkneme "udalosť" na zavesenie.
// Budeme očakávať, že to je funkcia.
poZmeneSmeru: null,
dajVedietOZmeneSmeru: function () {
if (this.poZmeneSmeru !== null) {
this.poZmeneSmeru(this.smer);
}
},
vlavoVbok: function () {
otocDolava();
this.smer = akyJeDalsiSmerVlavo(this.smer);
this.dajVedietOZmeneZmeneSmeru();
},
vpravoVbok: function () {
otocDoprava();
this.smer = akyJeDalsiSmerVpravo(this.smer);
this.dajVedietOZmeneSmeru();
},
};
<script>
karel.poZmeneSmeru = function (novySmer) {
const infoSmer = document.querySelector('#direction');
infoSmer.innerHTML = novySmer;
};
const btnStep = document.querySelector('#btn-step');
btnStep.addEventListener('click', function (event) {
karel.krok();
});
const btnLeft = document.querySelector('#btn-left');
btnLeft.addEventListener('click', function (event) {
karel.dolava();
});
const btnRight = document.querySelector('#btn-right');
btnRight.addEventListener('click', function (event) {
karel.doprava();
});
</script>
Ďakujem za pozornosť
Školenie JS 2020 - lekcia 07
By Milan Herda
Školenie JS 2020 - lekcia 07
- 572