A Getterek és Setterek függvények vagy metódusok, amelyeket változók értékeinek lekérdezésére és beállítására használnak. A getter-készlet fogalma gyakori a számítógépes programozásban: szinte minden magas szintű programozási nyelv rendelkezik a getterek és setterek megvalósításához szükséges szintaxissal, beleértve a JavaScipt.
Lapozzon tovább:
Ebben a bejegyzésben megnézzük, hogy mik azok a getterek, setterek, és hogyan hozhatjuk létre és használhatjuk őket JavaScriptben.
- Getterek-setterek és a kapszulázás
- Getterek és szetterek létrehozása
- 1. Módszerekkel
- 2. Kulcsszavakkal
- Melyik módszer a jobb?
- Oververwrite prevention
- Műveletek a gettereken és settereken belül
- Adatok védelme getterekkel és setterekkel
- Védtelen adatok
- 1. Block scoping
- 2. Funkció scoping
- 3. Adatvédelem scoping nélkül
- Mikor használjunk gettereket és settereket?
Getterek-setterek és a kapszulázás
A getterek és setterek ötletét mindig a kapszulázással együtt említik. A kapszulázást kétféleképpen lehet érteni.
Először is, ez az adatok elérésére és módosítására szolgáló getters-setters-trió beállítása. Ez a meghatározás akkor hasznos, ha bizonyos műveleteket, például érvényesítést kell végrehajtani az adatokon, mielőtt elmentjük vagy megtekintjük azokat – a getterek és setterek tökéletes otthont biztosítanak ehhez.
Második, van egy szigorúbb meghatározás, amely szerint a kapszulázás az adatok elrejtésére történik, hogy más kódból elérhetetlenné tegyük azokat, kivéve a gettereken és settereken keresztül. Így nem jutunk oda, hogy véletlenül felülírjuk a fontos adatokat a program valamelyik másik kódjával.
Getterek és szetterek létrehozása
1. Módszerekkel
Mivel a getterek és setterek alapvetően egy értéket lekérő/megváltoztató függvények, többféleképpen is létrehozhatjuk és használhatjuk őket. Az első mód:
var obj = { foo: 'this is the value of foo', getFoo: function() { return this.foo; }, setFoo: function(val) { this.foo = val; }}console.log(obj.getFoo());// "this is the value of foo"obj.setFoo('hello');console.log(obj.getFoo());// "hello"
Ez a legegyszerűbb módja a getterek és setterek létrehozásának. Van egy tulajdonság foo
és van két metódus: getFoo
és setFoo
a tulajdonság értékének visszaadására és hozzárendelésére.
2. Kulcsszavakkal
A getterek és setterek létrehozásának “hivatalosabb” és robusztusabb módja a get
és set
kulcsszavak használata.
A getter létrehozásához a get
kulcsszót a getter metódusként szolgáló függvény deklarációja elé kell tenni, a set
kulcsszót pedig ugyanígy kell használni egy setter létrehozásához. A szintaxis a következő:
var obj = { fooVal: 'this is the value of foo', get foo() { return this.fooVal; }, set foo(val) { this.fooVal = val; }}console.log(obj.foo);// "this is the value of foo"obj.foo = 'hello';console.log(obj.foo);// "hello"
Megjegyezzük, hogy az adatokat csak olyan tulajdonságnév (fooVal
) alatt lehet tárolni, amely különbözik a getter-setter metódusok nevétől (foo
), mert a getter-settert tartalmazó tulajdonság nem tartalmazhatja az adatokat is.
Melyik módszer a jobb?
Ha úgy dönt, hogy kulcsszavakkal hoz létre gettereket és settereket, akkor az adatok beállításához használhatja az assignment operátort, az adatok kinyeréséhez pedig a dot operátort, ugyanúgy, ahogyan egy hagyományos tulajdonság értékét is elérné/beállítaná.
Ha azonban a getterek és setterek kódolásának első módját választja, akkor a setter és getter metódusokat a függvényhívás szintaxisával kell meghívnia, mivel ezek tipikus függvények (semmi különleges, mint a get
és set
kulcsszavakkal létrehozott függvények).
Ezeken kívül megvan az esélye annak, hogy véletlenül valami más értéket rendel a getter-setter metódusokat tartalmazó tulajdonságokhoz, és teljesen elveszíti azokat! Ami miatt a későbbi módszerrel nem kell aggódnod.
Szóval, láthatod, miért mondtam, hogy a második technika robusztusabb.
Oververwrite prevention
Ha valamiért az első technikát részesíted előnyben, tedd a getter-setter metódusokat tartalmazó tulajdonságokat csak olvashatóvá, a Object.defineProperties
használatával létrehozva őket. A Object.defineProperties
, Object.defineProperty
és Reflect.defineProperty
segítségével létrehozott tulajdonságok automatikusan writable: false
-re konfigurálódnak, ami azt jelenti, hogy csak olvasható:
/* Overwrite prevention */var obj = { foo: 'this is the value of foo'};Object.defineProperties(obj, { 'getFoo': { value: function () { return this.foo; } }, 'setFoo': { value: function (val) { this.foo = val; } }});obj.getFoo = 66;// getFoo is not going to be overwritten!console.log(obj.getFoo());// "this is the value of foo"
Műveletek a gettereken és settereken belül
Ha már bevezetted a gettereket és settereket, mehetsz előre, és végezhetsz műveleteket az adatokon, mielőtt megváltoztatod vagy visszaadod azokat.
A lenti kódban a getter függvényben az adatot a visszaküldés előtt egy sztringgel kapcsoljuk össze, a setter függvényben pedig a n
frissítése előtt elvégezzük annak ellenőrzését, hogy az érték szám-e vagy sem.
var obj = { n: 67, get id() { return 'The ID is: ' + this.n; }, set id(val) { if (typeof val === 'number') this.n = val; }}console.log(obj.id);// "The ID is: 67"obj.id = 893;console.log(obj.id);// "The ID is: 893"obj.id = 'hello';console.log(obj.id);// "The ID is: 893"
Adatok védelme getterekkel és setterekkel
Ezidáig a getterek és setterek használatát a kapszulázás első összefüggésében tárgyaltuk. Térjünk át a másodikra, vagyis arra, hogyan rejtsük el az adatokat a külső kód elől a getterek és setterek segítségével.
Védtelen adatok
A getterek és setterek beállítása nem jelenti azt, hogy az adatokat csak ezeken a metódusokon keresztül lehet elérni és módosítani. A következő példában közvetlenül, a getter és setter metódusok érintése nélkül változtatjuk meg:
var obj = { fooVal: 'this is the value of foo', get foo() { return this.fooVal; }, set foo(val) { this.fooVal = val; }}obj.fooVal = 'hello';console.log(obj.foo);// "hello"
Nem használtuk a settert, hanem közvetlenül változtattuk meg az adatokat (fooVal
). Az adat, amit eredetileg a obj
belsejében állítottunk be, most eltűnt! Ahhoz, hogy ez ne történhessen meg (véletlenül), szükség van az adatok védelmére. Ezt úgy adhatod hozzá, hogy korlátozod az adatod elérhetőségének hatókörét. Ezt vagy blokkhatárral, vagy függvényhatárral teheti meg.
1. Block scoping
Egyik mód a blokk hatókörének használata, amelyen belül az adatokat a let
kulcsszóval határozzuk meg, amely a hatókörét az adott blokkra korlátozza.
A blokk hatókörét úgy hozhatjuk létre, hogy a kódot egy pár szögletes zárójelbe helyezzük. Amikor létrehoz egy blokk hatókörét, mindenképpen hagyjon felette egy megjegyzést, amelyben kéri, hogy a szögletes zárójeleket hagyják békén, hogy senki ne távolítsa el véletlenül a szögletes zárójeleket, azt gondolva, hogy azok néhány extra felesleges zárójelek a kódban, vagy adjon egy címkét a blokk hatóköréhez.
/* BLOCK SCOPE, leave the braces alone! */{let fooVal = 'this is the value of foo';var obj = { get foo() { return fooVal; }, set foo(val) { fooVal = val } }}fooVal = 'hello';// not going to affect the fooVal inside the blockconsole.log(obj.foo);// "this is the value of foo"
A blokkon kívüli fooVal
módosítása/alkotása nem befolyásolja a fooVal
hivatkozott fooVal
-t a getters setters-en belül.
2. Funkció scoping
Az adatok scopinggal történő védelmének gyakoribb módja az, hogy az adatokat egy függvényen belül tartjuk, és egy objektumot adunk vissza a getterekkel és setterekkel a függvényből.
function myobj(){ var fooVal = 'this is the value of foo'; return { get foo() { return fooVal; }, set foo(val) { fooVal = val } }}fooVal = 'hello';// not going to affect our original fooValvar obj = myobj();console.log(obj.foo);// "this is the value of foo"
A myobj()
függvény által visszaadott objektumot (benne a foo()
getter-készítővel) a obj
-ban tároljuk, majd a obj
-t használjuk a getter és setter hívására.
3. Adatvédelem scoping nélkül
Létezik egy másik mód is arra, hogy a hatókör korlátozása nélkül védjük az adatokat a felülírástól. A logika mögötte a következő: Hogyan tudnánk megváltoztatni egy adatot, ha nem tudjuk, hogy minek hívják?
Ha az adatnak van egy nem túl könnyen reprodukálható változó/tulajdonság neve, akkor jó eséllyel senki (még mi magunk sem) nem fogja végül felülírni azt úgy, hogy valamilyen értéket rendelünk ehhez a változó/tulajdonság nevéhez.
var obj = { s89274934764: 'this is the value of foo', get foo() { return this.s89274934764; }, set foo(val) { this.s89274934764 = val; }}console.log(obj.foo);// "this is the value of foo"
Nézd, ez az egyik módja a dolgok megoldásának. Bár az általam választott név nem igazán jó, használhatsz véletlenszerű értékeket vagy szimbólumokat is a tulajdonságnevek létrehozásához, ahogy azt Derick Bailey javasolja ebben a blogbejegyzésben. A fő cél az, hogy az adatokat rejtve tartsuk más kódok elől, és egy getter-setter páros segítségével érjük el/frissítsük őket.
Mikor használjunk gettereket és settereket?
Most jön a nagy kérdés: most már minden adatunkhoz elkezdünk gettereket és settereket rendelni?
Ha elrejted az adatokat, akkor nincs más választásod.
De ha az adataidat más kód látja, akkor is használnod kell gettereket és settereket, csak azért, hogy összekapcsold őket olyan kóddal, amely végrehajt rajtuk néhány műveletet? Én azt mondanám, hogy igen. A kód nagyon hamar összeadódik. Az egyedi adatok mikroegységeinek létrehozása saját getter-készletezővel bizonyos függetlenséget biztosít az említett adatokon való munkához anélkül, hogy a kód más részeit befolyásolná.
Lássuk még: 10 ok, amiért szükséged van kódoptimalizálásra