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.

Člen

Zobrazeno 13 zpráv z 13.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
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.