.
Koncept getterů a setterů je mezi dnes používanými populárními jazyky zcela běžný. Potřebovali jste někdy zajistit, aby se daná akce provedla vždy před nebo po přiřazení nějaké hodnoty vlastnosti objektu? To je možné pomocí setterů. Pomocí getterů můžete také provádět libovolné zpracování při získávání hodnoty vlastnosti (např. formátování). Jedním ze způsobů implementace getterů a setterů je použití metod, jako je tomu v jazyce Java. Od verze ES5 však máme k dispozici mnohem elegantnější a praktičtější alternativu pomocí syntaxe get
a set
. Tak začněme!!!
V JavaScriptu jsou objekty kolekce vlastností a pravděpodobně jste je již někdy použili k ukládání dat. Vlastnost je jednoduše dvojice klíč-hodnota. Zde je příklad:
const options = {
timeout: 5000,
retries: 3,
ip: '192.168.1.20',
port: 4001,
};
Vlastnosti v objektu lze snadno nastavovat a číst, například takto:
artist.name = 'Carice Anouk van Houten';console.log(artist.name); //=> "Carice Anouk van Houten"
Znovu říkám, že to rozhodně není nic nového, pokud už máte s JavaScriptem nějaké zkušenosti. Abychom rozlišili mezi těmito běžnými vlastnostmi a dalším typem, který uvidíme v tomto článku, můžeme ty první nazývat „datové vlastnosti“.
Gettery a settery: starý způsob
Před ES5 jsme gettery a settery implementovali pouze pomocí běžných metod. Jako v příkladu níže:
V uvedeném příkladu jsem ponechal klíčové slovo function, aby bylo jasné, že zde nejde o žádnou magii. Pouze normální metody. Stejného efektu jsme mohli dosáhnout použitím syntaxe definice metod v ES2015, která je kratší a poněkud elegantnější:
const config = {
_port: 4001,
setPort(port) {
// ...
},
getPort() {
// ...
},
};
Použití těchto druhů getterů a setterů je poměrně jednoduché:
config.setPort(8080);
console.log(config.getPort()); //=> 8080
Inkrementace hodnoty by se provedla takto:
item.setQuantity(item.getQuantity() + 1);
Což vypadá opravdu mnohomluvně ve srovnání s přímou inkrementací vlastnosti:
item.quantity += 1;
// Or even simpler...
item.quantity++;
Gettery a settery: proč?
V OO jazycích, jako je Java, C++ nebo C#, je možné vystavit členy třídy na různých úrovních pomocí modifikátorů přístupu (například public
, protected
a private
). To slouží k implementaci důležitého konceptu OOP, který se nazývá skrývání dat.
Velmi častým použitím getterů a setterů v těchto jazycích je bezpečné vystavení členů třídy. Například můžete implementovat pouze getter, abyste zajistili, že soukromý člen nebude nikdy změněn z vnějšku třídy. Setter lze zase použít k ověření dodaných hodnot a zachování integrity instancí dané třídy.
A co JavaScript?
V JavaScriptu je to trochu jinak. V době psaní tohoto článku neexistují v JS žádné modifikátory přístupu. V současné době je nejlepší možností, kterou máme, použití symbolů, které nám při použití jako klíče poskytují určitou úroveň soukromí. Někteří lidé je však nemají rádi. Zejména proto, že je snadné toto soukromí porušit použitím reflexe.
Nepovažuji to za skutečný problém, protože jazyky, které mají reflexi, obvykle umožňují programátorům zapouzdření nějakým způsobem porušit. Problém v symbolech vidím v tom, že jejich použití není tak praktické, jako by byl jednoduchý privátní accessor. Dobrou zprávou je, že návrh EcmaScriptu, který zahrnuje soukromá pole, je již ve fázi 3. A ta budou imunní vůči jakémukoli druhu reflexe.
V příkladu z předchozí části jsme nepoužili symboly ani žádný jiný trik k simulaci soukromého členu. Vlastnost _port
sama o sobě nemá nic zvláštního. Je to prostě obyčejná datová vlastnost a jako takovou ji lze nastavovat nebo číst přímo, zcela obchází getter a setter, které jsme vytvořili.
Protože vysvětlování symbolů a jiných zapouzdřovacích technik není účelem tohoto článku, neimplementuji v jeho příkladech kódu privátní vlastnosti. Jen mějte na paměti, že gettery a settery se běžně (ale ne vždy) používají k zajištění přístupu k zapouzdřeným členům. Nakonec si všimněte podtržítka před názvem vlastnosti _port
. Je to de facto konvence mezi vývojáři JS, která označuje, že daná vlastnost je soukromá a neměla by být přístupná mimo třídu, kde je definována.
Gettery a settery: nový způsob s vlastnostmi accessor
Vlastnosti accessor jsou moderním způsobem definování getterů a setterů. Pokud jde o jejich definici, příliš se neliší od našeho předchozího příkladu, ale skutečně odlišné je jejich použití. Nejprve upravíme náš kód tak, aby používal vlastnosti accessor:
Jak vidíte, v tomto příkladu se změnily pouze dvě věci:
- Místo metod
setPort
agetPort
. Používáme syntaxiset
aget
spolu s jediným názvem vlastnosti („port
„, v tomto příkladu) - Klíčové slovo
function
zde nepotřebujeme. Ve skutečnosti, pokud se ho pokusíte použít, dostanete chybu SyntaxError.
Jak používat vlastnosti accessor?
Pokud je definice vlastnosti accessor docela podobná tomu, jak vytváříme gettery a settery ze staré školy, jejich použití nemá žádný viditelný rozdíl od toho, jak používáme běžné datové vlastnosti:
config.port = 8080;
console.log(config.port); //=> 8080
A tady je, jak vypadá přírůstkový výraz:
timer.seconds += 1;
Ano. Je to tak jednoduché. =)
Závěr
- Objekty jsou kolekce vlastností
- Obvyklá vlastnost je jen dvojice klíč-hodnota a lze ji nazvat „datovou vlastností“
- Můžete implementovat gettery a settery jako běžné metody. To je v JavaScriptu „stará škola“.
- Gettery a settery se obvykle používají k zajištění přístupu k privátním členům třídy.
- Vlastnosti typu accessor se mohou chovat přesně jako gettery a settery založené na starých běžných metodách, ale jejich použití je navrženo tak, aby vypadaly jako datové vlastnosti.
Chcete ovládat JavaScript? Vřele doporučuji Moshovy kurzy JavaScriptu.
A pokud se vám tento článek líbil, podělte se o něj i s ostatními!