Objekty se obvykle vytváÅejà tak, aby pÅedstavovaly entity ze skuteÄného svÄta, napÅÃklad uživatele, objednávky a podobnÄ:
let uživatel = {
jméno: "Jan",
vÄk: 30
};
A ve skuteÄném svÄtÄ může uživatel konat nÄjakou akci: vybrat si nÄco z nákupnÃho vozÃku, pÅihlásit se, odhlásit se atd.
V JavaScriptu jsou tyto akce reprezentovány funkcemi ve vlastnostech.
PÅÃklady metod
Pro zaÄátek nauÄme objekt uživatel ÅÃci ahoj:
let uživatel = {
jméno: "Jan",
vÄk: 30
};
uživatel.ÅekniAhoj = function() {
alert("Ahoj!");
};
uživatel.ÅekniAhoj(); // Ahoj!
PrávÄ jsme použili funkÄnà výraz, kterým jsme vytvoÅili funkci a pÅiÅadili ji do vlastnosti objektu uživatel.ÅekniAhoj.
Pak ji můžeme volat pomocà uživatel.ÅekniAhoj(). Uživatel nynà umà mluvit!
Funkce, která je vlastnostà objektu, se nazývá jeho metoda.
Zde tedy máme metodu ÅekniAhoj objektu uživatel.
SamozÅejmÄ můžeme použÃt jako metodu pÅedem deklarovanou funkci, napÅÃklad takto:
let uživatel = {
// ...
};
// nejprve ji deklarujeme
function ÅekniAhoj() {
alert("Ahoj!");
};
// pak pÅidáme jako metodu
uživatel.ÅekniAhoj = ÅekniAhoj;
uživatel.ÅekniAhoj(); // Ahoj!
Způsob programovánÃ, pÅi kterém pÃÅ¡eme kód, který použÃvá objekty pÅedstavujÃcà entity, se nazývá objektovÄ orientované programovánÃ, zkrácenÄ âOOPâ.
OOP je velká vÄc a samo o sobÄ je zajÃmavou vÄdou. Jak zvolit správné entity? Jak zorganizovat interakci mezi nimi? To je architektura a o tomto tématu existujà skvÄlé knihy, napÅ. âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ od E. Gammy, R. Helma, R. Johnsona a J. Vissidese, nebo âObject-Oriented Analysis and Design with Applicationsâ od G. Booche a dalÅ¡Ã.
Zkratky metod
V objektovém literálu existuje i kratšà syntaxe metod:
// tyto objekty dÄlajà totéž
uživatel = {
ÅekniAhoj: function() {
alert("Ahoj");
}
};
// zkratka metody vypadá lépe, že?
uživatel = {
ÅekniAhoj() { // totéž jako âÅekniAhoj: function(){...}â
alert("Ahoj");
}
};
Jak vidÃme, můžeme vypustit slovo "function" a napsat jen ÅekniAhoj().
UpÅÃmnÄ ÅeÄeno, tyto notace nejsou zcela identické. Jsou v nich drobné rozdÃly týkajÃcà se objektové dÄdiÄnosti (která bude vysvÄtlena pozdÄji), ale na nich nám prozatÃm nezáležÃ. TémÄÅ ve vÅ¡ech pÅÃpadech se dává pÅednost kratšà syntaxi.
âthisâ v metodách
BÄžnÄ se stává, že objektová metoda potÅebuje pÅÃstup k informaci uložené v objektu, aby mohla vykonat svou práci.
NapÅÃklad kód uvnitÅ uživatel.ÅekniAhoj() může potÅebovat jméno objektu uživatel.
K pÅÃstupu do objektu může metoda použÃvat klÃÄové slovo this.
Hodnota this je objekt âpÅed teÄkouâ, tedy ten, který byl použit k volánà metody.
NapÅÃklad:
let uživatel = {
jméno: "Jan",
vÄk: 30,
ÅekniAhoj() {
// âthisâ je âaktuálnà objektâ
alert(this.jméno);
}
};
uživatel.ÅekniAhoj(); // Jan
Zde bÄhem výkonu uživatel.ÅekniAhoj() hodnota this bude uživatel.
Technicky je možné pÅistupovat k objektu i bez this tak, že se na nÄj odkážeme pÅes vnÄjšà promÄnnou:
let uživatel = {
jméno: "Jan",
vÄk: 30,
ÅekniAhoj() {
alert(uživatel.jméno); // âuživatelâ namÃsto âthisâ
}
};
â¦Takový kód je vÅ¡ak nespolehlivý. Pokud se rozhodneme zkopÃrovat objekt uživatel do jiné promÄnné, napÅ. správce = uživatel, a pÅepsat promÄnnou uživatel nÄÄÃm jiným, pak budeme pÅistupovat k nesprávnému objektu.
To je ukázáno zde:
let uživatel = {
jméno: "Jan",
vÄk: 30,
ÅekniAhoj() {
alert( uživatel.jméno ); // povede k chybÄ
}
};
let správce = uživatel;
uživatel = null; // pÅepÃÅ¡eme, aby to bylo zÅejmé
správce.ÅekniAhoj(); // TypeError: Cannot read property 'jméno' of null
Kdybychom uvnitÅ alert použili this.jméno namÃsto uživatel.jméno, kód by fungoval.
âthisâ nenà vázané
V JavaScriptu se klÃÄové slovo this chová jinak než ve vÄtÅ¡inÄ ostatnÃch programovacÃch jazyků. Může být použito v libovolné funkci, i když to nenà metoda objektu.
V následujÃcÃm pÅÃkladu nenà žádná syntaktická chyba:
function ÅekniAhoj() {
alert( this.jméno );
}
Hodnota this se vyhodnocuje za bÄhu skriptu v závislosti na kontextu.
NapÅÃklad zde bude stejná funkce pÅiÅazena dvÄma různým objektům a ve volánÃch bude mÃt různá âthisâ:
let uživatel = { jméno: "Jan" };
let správce = { jméno: "Správce" };
function ÅekniAhoj() {
alert( this.jméno );
}
// použijeme stejnou funkci ve dvou objektech
uživatel.f = ÅekniAhoj;
správce.f = ÅekniAhoj;
// tato volánà majà různá this
// âthisâ uvnitÅ funkce je objekt âpÅed teÄkouâ
uživatel.f(); // Jan (this == uživatel)
správce.f(); // Správce (this == správce)
správce['f'](); // Správce (k metodÄ pÅistupuje teÄka nebo hranaté závorky - na tom nezáležÃ)
Platà jednoduché pravidlo: je-li volána obj.f(), pak this bÄhem volánà f je obj. Ve výše uvedeném pÅÃkladu je to tedy uživatel anebo správce.
this == undefinedMůžeme tuto funkci volat dokonce zcela bez objektu:
function ÅekniAhoj() {
alert(this);
}
ÅekniAhoj(); // undefined
Ve striktnÃm režimu je this v tomto pÅÃpadÄ undefined. Pokud se pokusÃme pÅistoupit k this.jméno, nastane chyba.
V nestriktnÃm režimu bude hodnota this v takovém pÅÃpadÄ globálnà objekt (v prohlÞeÄi window, dostaneme se k tomu pozdÄji v kapitole Globálnà objekt). To je historické chovánÃ, které "use strict" opravuje.
Takové volánà je obvykle programovacà chyba. Jestliže je this uvnitÅ funkce, oÄekává se, že funkce bude volána v kontextu objektu.
thisPokud pÅicházÃte z jiného programovacÃho jazyka, pak jste pravdÄpodobnÄ zvyklà na myÅ¡lenku âvázaného thisâ, kdy v metodách definovaných v nÄjakém objektu this vždy odkazuje na tento objekt.
V JavaScriptu je this âvolnéâ, jeho hodnota se vypoÄÃtává až pÅi volánà a nenà závislá na tom, kde byla metoda deklarována, ale jen na tom, jaký objekt je âpÅed teÄkouâ.
Koncept vyhodnocovánà this za bÄhu má své výhody i nevýhody. Na jednu stranu můžeme tutéž funkci použÃt opakovanÄ pro různé objekty. Na druhou stranu vÄtšà flexibilita vytváÅà vÃce prostoru pro chyby.
Zde nám nepÅÃslušà soudit, zda je toto rozhodnutà návrháÅů jazyka dobré nebo Å¡patné. PorozumÃme tomu, jak s nÃm pracovat, jak využÃt jeho výhody a vyhnout se problémům.
Å ipkové funkce nemajà âthisâ
Å ipkové funkce jsou zvláštnÃ: nemajà âsvé vlastnÃâ this. Pokud se v takové funkci odkážeme na this, bude pÅevzato z vnÄjšà ânormálnÃâ funkce.
NapÅÃklad zde Å¡ipka() použÃvá this z vnÄjšà metody uživatel.ÅekniAhoj():
let uživatel = {
kÅestnÃJméno: "Ilja",
ÅekniAhoj() {
let Å¡ipka = () => alert(this.kÅestnÃJméno);
šipka();
}
};
uživatel.ÅekniAhoj(); // Ilja
To je speciálnà vlastnost Å¡ipkových funkcÃ. Je užiteÄná, když ve skuteÄnosti nechceme mÃt oddÄlené this, ale chceme je pÅevzÃt z vnÄjÅ¡Ãho kontextu. PozdÄji v kapitole Å ipkové funkce podruhé prozkoumáme Å¡ipkové funkce vÃce do hloubky.
ShrnutÃ
- Funkce uložené ve vlastnostech objektu se nazývajà âmetodyâ.
- Metody umožÅujà objektům âkonat akceâ, napÅ.
objekt.dÄlejNÄco(). - Metody se na tento objekt mohou odkazovat klÃÄovým slovem
this.
Hodnota this je definována za bÄhu skriptu.
- Když je funkce deklarována, může použÃvat
this, ale totothisnemá žádnou hodnotu, dokud nenà funkce volána. - Funkce může být kopÃrována mezi objekty.
- Když je funkce volána âmetodovouâ syntaxÃ
objekt.metoda(), hodnotathisbÄhem tohoto volánà jeobjekt.
ProsÃme vÅ¡imnÄte si, že Å¡ipkové funkce jsou zvláštnÃ: nemajà this. Když uvnitÅ Å¡ipkové funkce pÅistoupÃme k this, pÅevezme se zvnÄjÅ¡ku.
KomentáÅe
<code>, pro nÄkolik Åádků je obalte znaÄkou<pre>, pro vÃce než 10 Åádků vložte odkaz na pÃskoviÅ¡tÄ (plnkr, jsbin, codepenâ¦)