Diskuze: Práce s objekty - Error x is not a function
V předchozím kvízu, Online test znalostí JavaScript, jsme si ověřili nabyté zkušenosti z kurzu.


Zobrazeno 13 zpráv z 13.
K personalizaci obsahu a reklam, poskytování funkcí sociálních médií a analýze naší návštěvnosti využíváme soubory cookie. Informace o tom, jak náš web používáte, sdílíme se svými partnery pro sociální média, inzerci a analýzy. Partneři tyto údaje mohou zkombinovat s dalšími informacemi, které jste jim poskytli nebo které získali v důsledku toho, že používáte jejich služby.
Používáme nezbytné cookies pro fungování webu a s tvým souhlasem také analytické a marketingové cookies.
Zajišťují základní funkce, bezpečnost a služby, které sis vyžádal. Nelze je vypnout.
| Služba | Poskytovatel | Účel | Cookies a úložiště | Doba uložení |
|---|---|---|---|---|
| ITnetwork | ITnetwork | Provoz webu, relace, přihlášení a uložení nastavení cookies. | PHPSESSID, auth_token, sid, itn_consent_impression, __Host-itn_consent | Relace až 1 rok |
| Google Tag Manager | Správa značek a načítání měřicích nástrojů webu. | Žádné | Neukládá se | |
| Google Fonts | Načítání typografie webu. | Úložiště řízené poskytovatelem | Dle podmínek poskytovatele | |
| Google Hosted Libraries | Načítání potřebných knihoven a stylů webu. | Úložiště řízené poskytovatelem | Dle podmínek poskytovatele | |
| Google reCAPTCHA | Ochrana formulářů a webu před zneužitím. | _GRECAPTCHA, rc::a, rc::b, rc::c, rc::f | Relace až 180 dní | |
| YouTube | Přehrávání vloženého video obsahu. | localStorage, IndexedDB; cookies after playback interaction | Relace až trvalé úložiště | |
| Vimeo | Vimeo | Přehrávání vloženého video obsahu. | __cf_bm, _cfuvid, vuid, localStorage, IndexedDB | Relace až 2 roky |
| Facebook Login | Meta | Přihlášení pomocí účtu třetí strany. | Úložiště řízené poskytovatelem | Relace až 1 rok |
| GoPay | GoPay | Zpracování uživatelem vyžádané platby. | Úložiště řízené poskytovatelem | Dle podmínek poskytovatele |
Pomáhají nám porozumět používání webu a zlepšovat ho.
| Služba | Poskytovatel | Účel | Cookies a úložiště | Doba uložení |
|---|---|---|---|---|
| Google Analytics 4 | Měření návštěvnosti a používání webu. | _ga, _ga_* | Až 2 roky | |
| Microsoft Clarity | Microsoft | Měření návštěvnosti a používání webu. | _clck, _clsk, _cltk | Relace až 1 rok |
Slouží k měření kampaní, personalizaci reklamy a marketingové komunikaci.
| Služba | Poskytovatel | Účel | Cookies a úložiště | Doba uložení |
|---|---|---|---|---|
| Google Ads | Měření kampaní, reklama a remarketing. | _gcl_au, _gcl_ls | Relace až 90 dní | |
| Meta Pixel | Meta | Měření kampaní, reklama a remarketing. | _fbp, _fbc, localStorage | Až 90 dní |
| Sklik | Seznam.cz | Měření kampaní, reklama a remarketing. | retargeting, sid, szn:* | Relace až trvalé úložiště |
| LinkedIn Insight | Měření kampaní, reklama a remarketing. | bcookie, li_gc, lidc, __cf_bm | Relace až 1 rok | |
| Ecomail | Ecomail.cz | Měření kampaní, reklama a remarketing. | ecmid, Úložiště řízené poskytovatelem | Dle podmínek poskytovatele |
| Atribuce kampaní ITnetwork | ITnetwork | Přiřazení návštěvy a objednávky ke kampani. | campaign_clid[*], user_session_context | Až 1 rok |
V předchozím kvízu, Online test znalostí JavaScript, jsme si ověřili nabyté zkušenosti z kurzu.


Ahoj, nemá být nahodou v tom addEventListener("click",
createMemberForm);
Na místo toho to ? mDB.createMemberForm) ?
Muzes z toho vseho vycucat kod a vyrobit jednoduchy priklad? Radi bycho si tu hlasku vygenerovali sami. Takhle je to spis tipovacka naslepo jen podle kodu, kde nemusi byt chyba.
this.createMember is not a function // pise, ze to neni funkce. tak si to alertni a zjisti, co to je?
HTMLButtonElement.createMemberForm // tady pise, ze to vola z buttonu. Coz je nesmysl.
// btn.addEventListener("click", mDB.createMemberForm);
// timhle navazujes na buton nejakou externi funkci, ale, pokud mas tento radek spatne a mas tam this, pak ta hlaska dava smysl
// btn.addEventListener("click", this.createMemberForm); // this v tomto pripade odkazuje nejspis na button a ten funkci createMemberForm nema
A z toho erroru jsi vynechal cislo radku, ktery by mohl byt zasadni.
Ahoj, než se tu začnou rozvíjet nějaké bludné teorie, nejdříve napíšu řešení a pak vysvětlení.
ŘEŠENÍ
btn.addEventListener("click", mDB.createMemberForm.bind(mDB));
// nebo
btn.addEventListener("click", () => mDB.createMemberForm());
VYSVĚTLENÍ
"Problém je v tzv. scope. V JS to funguje maličko jinak než v ostatních OOP
jazycích co se týče ukazatele this a tohle je jeden z těch
podivných případů.
Ve tvé ukázce jsi předal funkci createMemberForm jako parametr
addEventListener. Když pak nastane událost kliknutí na tlačítko,
ukazatel this bude ukazovat na kontext toho kliknutí a ne na
instanci tvojí MemberDatabase jak by se dalo očekávat.
Na zkoušku si můžeš vypsat do konzole, na co ukazatel this
ukazuje ve tvém případě.
Měl bys vidět něco takového:
<button id="createMemberBtn">
.....
To znamená, že this je vlastně to tlačítko samotné a
vůbec neukazuje na MemberDatabase.
První příklad v řešení je použití "magické" metody bind,
která právě změní kontext, takže this už bude tvoje
MemberDatabase.
Druhý příklad v řešení používá jednoduše anonymní funkci, ve které
se teprve metoda createMemberForm zavole. Tím se opět změní kontext
a this už bude ukazovat na správnou instanci.
Doufám, že je to pochopitelný 
btn.addEventListener("click", mDB.createMemberForm); // 1
btn.addEventListener("click", mDB.createMemberForm.bind(mDB)); // 2
1 a 2 jsou zatracene rozdil.
//1
var xxx = function (event) {...}
btn.addEventListener("click", xxx);
// 1
function yyy (event) {...}
btn.addEventListener("click", yyy);
// 3
function zzz (cokoliv) {...}
btn.addEventListener("click", function (event) { zzz(neco); } ); // nebo...
btn.addEventListener("click", (event) => zzz(neco); );
// 2
alert(aaa.funkce.bind(bbb)) // vysledek bind operace returnuje true nebo false a boolean preci neni typu function
//console.log(aaa.funkce.bind(bbb))
btn.addEventListener("click", aaa.funkce.bind(bbb));
btn.addEventListener("click", true); // true neni event
O bind jinak nic nevim, tak s tim ti neporadim. Ja bych se tomu prikazu spis vyhl.
Aha, tak koukam, ze je problem jiny. Tu moji odpoved k BIND uplne ignoruj.
Koukal jsem do dokumentace a bind skutecne vraci puvodni objekt https://developer.mozilla.org/…unction/bind
A nebo by asi fungovalo tez
// this.createMember(name, role, status);
mDB.createMember(name, role, status);
Kdyz totiz vola event, tak this pro ne plati na puvodni objekt, ve kterem
event vytvaris. Coz je btn.
Na podobny problem narazis i pri praci setInterval.
oprava: Kdyz totiz volas event, tak this je objekt, ve kterem event vytvaris. Coz je btn. Ikdyz to mas mysleno jinak a v jinych jazycich je to ok. Je to takova chybka js pro vsechny eventy.
btn.addEventListener("click", mDB.createMemberForm); // je skoro totez jako
bt.onclick = mDB.createMemberForm;
alert (bt.onclick); // alert ti pak zobrazi js kod funkce
// a kdybys to napsal primo, tak je ti to asi jasne
bt.onclick = function() {/*...*/ this.createMember(name, role, status); /*...*/ }
V tomto pripade je celkem jasne, ze this odkazuje na button. A to presne
prohlizec udela, zkopiruje text kodu a znovu jej prelozi
Je to jakysi bug JS a nespis se to hned tak nezmeni, pac vsechny stranky s tim
pocitaji.
Jestli jsou nejake dalsi priklady, tak se tykaji asynchronich udalosti, jako
treba cteni souboru, dat, httprequest a jak jsem psal, casovacu setTimeout,
setInterval. Proste, spesl udalost/event, ktery bezi nezavisle na ostatnim kodu,
v jinem vlakne, jakoby.
Wtf? xDDDD
Petr Štechmüller tu naprosto spravne napise jak to s tim this je a ze nemuzes jen tak nekam narvat metodu protoze ztratis kontext toho ze je to medota -> je treba to nabindovat na puvodni objekt ..
.. a pak tady Peter Mlich napise roman o tom ze by to nepouzival a ze nevi co
je bind.
KEKW
no koukam, ze nakonec se to vyresilo spravne ..
Co ja vim tak this vraci ten dotycny HTML element jenom pri eventListenerech, protoze je to sikovne, ale clovek musi vedet jak funguje JS jinak padne do podobnych pasti.
Uz jen z toho ze je to nejaka funkce ktera prebira jen jinou funkci muzes
(pokud vis jak funcuje JS) automaticky rict ze je spatny napad tam predavat
metodu jen tak a ocekavat ze ona bude vedet z jakeho objektu pochazi -
nebude.
JS je velmi tvarny a klidne si muzes pujcovat metody objektu a pouzivat je jako
funkce nekde uplne jinde, volat je s jinym kontextem, na jinych objektech atd.

Zobrazeno 13 zpráv z 13.