A getterek és setterek fogalma meglehetősen elterjedt a ma használatos népszerű nyelvek között. Volt már szüksége arra, hogy biztosítsa, hogy egy adott művelet mindig egy objektum tulajdonságának valamilyen érték hozzárendelése előtt vagy után kerüljön végrehajtásra? Ez a setterekkel lehetséges. A getterek segítségével bármilyen feldolgozást elvégezhetünk egy tulajdonság értékének lekérdezésekor is (pl. formázás). A getterek és setterek implementálásának egyik módja a metódusok használata, ahogyan az a Java-ban történik. Az ES5 óta azonban egy sokkal elegánsabb és praktikusabb alternatíva áll rendelkezésünkre a get
és set
szintaxis használatával. Nos, kezdjük el!
A JavaScriptben az objektumok tulajdonságok gyűjteményei, és valószínűleg már korábban is használtad őket adatok tárolására. Egy tulajdonság egyszerűen egy kulcs-érték pár. Íme egy példa:
const options = {
timeout: 5000,
retries: 3,
ip: '192.168.1.20',
port: 4001,
};
A tulajdonságok egy objektumban egyszerűen beállíthatók és kiolvashatók, például így:
artist.name = 'Carice Anouk van Houten';console.log(artist.name); //=> "Carice Anouk van Houten"
Még egyszer, ez biztosan nem újdonság, ha már volt némi tapasztalatod a JavaScriptben. Hogy megkülönböztessük ezeket a szabályos tulajdonságokat a másik típustól, amit ebben a cikkben látni fogunk, az előbbieket nevezhetjük “adattulajdonságoknak”.
Getterek és setterek: a régi módszer
Az ES5 előtt a gettereket és settereket csak szabályos metódusokkal tudtuk megvalósítani. Mint az alábbi példában:
A fenti példában megtartottam a function kulcsszót, hogy egyértelmű legyen, hogy itt nincs varázslat. Csak normál metódusok. Ugyanezt a hatást elérhettük volna az ES2015 módszerdefiníciós szintaxisával is, ami rövidebb és valamivel elegánsabb:
const config = {
_port: 4001,
setPort(port) {
// ...
},
getPort() {
// ...
},
};
Az ilyen típusú getterek és setterek használata meglehetősen egyszerű:
config.setPort(8080);
console.log(config.getPort()); //=> 8080
Egy érték inkrementálása így történne:
item.setQuantity(item.getQuantity() + 1);
Ami nagyon terjedelmesnek tűnik, ha összehasonlítjuk egy tulajdonság közvetlen inkrementálásával:
item.quantity += 1;
// Or even simpler...
item.quantity++;
Getterek és setterek: miért?
Az olyan OO nyelvekben, mint a Java, a C++ vagy a C#, lehetőség van arra, hogy egy osztály tagjait különböző szinteken tegyük hozzáférhetővé hozzáférési módosítókkal (például public
, protected
és private
). Ez az OOP egyik fontos koncepciójának, az adatelrejtésnek a megvalósítására szolgál.
A getterek és setterek nagyon gyakori használata ezekben a nyelvekben az osztály tagjainak biztonságos módon történő felfedésére. Például csak egy gettert implementálhatunk annak biztosítására, hogy egy privát tagot soha ne lehessen az osztályon kívülről megváltoztatni. A setter viszont használható a megadott értékek érvényesítésére és az adott osztály példányainak integritásának megőrzésére.
Hogyan áll a JavaScript?
A JavaScriptben a dolgok egy kicsit másképp állnak. A cikk megírásának időpontjában a JS-ben nincsenek hozzáférési módosítók. Jelenleg a legjobb lehetőségünk a szimbólumok használata, amelyek bizonyos szintű adatvédelmet biztosítanak, ha kulcsként használjuk őket. Néhányan azonban nem szeretik őket. Különösen azért, mert a reflexió használatával könnyen fel lehet törni ezt a titkosságot.
Nem tartom ezt valódi problémának, mivel azok a nyelvek, amelyekben van reflexió, általában lehetővé teszik a programozók számára, hogy valamilyen módon felbontsák a kapszulázást. A szimbólumokban azt látom a problémát, hogy nem olyan praktikus a használatuk, mint amilyen egy egyszerű privát accessor lenne. A jó hír az, hogy a privát mezőket tartalmazó EcmaScript javaslat már a 3. fázisban van. És ezek immunisak lesznek mindenféle reflexióra.
Az előző szakasz példájában nem használtunk szimbólumokat vagy bármilyen más trükköt a privát tag szimulálására. A _port
tulajdonságnak önmagában nincs semmi különleges tulajdonsága. Ez csak egy közönséges adattulajdonság, és mint ilyen, közvetlenül beállítható vagy olvasható, teljesen megkerülve az általunk létrehozott gettert és settert.
Mivel a szimbólumok és egyéb kapszulázási technikák magyarázata nem célja ennek a cikknek, ezért a kódpéldákban nem implementálom a privát tulajdonságokat. Csak tartsuk észben, hogy a gettereket és settereket általában (de nem mindig) a kapszulázott tagokhoz való hozzáférés biztosítására használják. Végezetül figyeljük meg a _port
tulajdonság neve előtti aláhúzást. Ez egy de facto konvenció a JS fejlesztők körében, ami azt jelzi, hogy egy adott tulajdonság privát, és nem lehet elérni azon az osztályon kívülről, ahol definiálták.
Getterek és setterek: az új út az accessor tulajdonságokkal
Az accessor tulajdonságok a getterek és setterek definiálásának modern módja. A definíciójukat tekintve nem sokban különböznek az előző példánktól, de a használatuk az, ami igazán más. Először is igazítsuk át a kódunkat az accessor tulajdonságok használatára:
Mint láthatjuk, ebben a példában csak két dolog változott:
- Az
setPort
ésgetPort
metódusok helyett. Aset
ésget
szintaxist használjuk a tulajdonság egyetlen nevével együtt (“port
“, ebben a példában) - A
function
kulcsszóra itt nincs szükségünk. Valójában, ha megpróbáljuk használni, SyntaxError-t kapunk.
Hogyan használjuk a hozzáférési tulajdonságokat?
Ha a hozzáférési tulajdonságok definíciója nagyon hasonló ahhoz, ahogyan a régi iskolai gettereket és settereket létrehozzuk, a használatuk nem mutat látható különbséget ahhoz képest, ahogyan a normál adattulajdonságokat használjuk:
config.port = 8080;
console.log(config.port); //=> 8080
És így néz ki egy inkrementálási kifejezés:
timer.seconds += 1;
Igen. Ilyen egyszerű. =)
Következtetés
- A tárgyak tulajdonságok gyűjteményei
- A hagyományos tulajdonság csak egy kulcs-érték pár, és nevezhetjük “adattulajdonságnak”
- A gettereket és settereket normál metódusként implementálhatjuk. Ez a “régi iskola” módja a JavaScriptben.
- A gettereket és settereket általában arra használják, hogy hozzáférést biztosítsanak egy osztály privát tagjaihoz.
- Accessor tulajdonságok pontosan úgy viselkedhetnek, mint a régi, szabályos metódus alapú getterek és setterek, de a használatuk úgy van kialakítva, hogy adattulajdonságoknak tűnjenek.
A JavaScriptet szeretné elsajátítani? Nagyon ajánlom a Mosh JavaScript tanfolyamait.
És ha tetszett ez a cikk, oszd meg másokkal is!