Begreppet getters och setters är ganska vanligt bland populära språk som används idag. Har du någonsin behövt se till att en viss åtgärd alltid utförs före eller efter att du har tilldelat ett visst värde till ett objekts egenskap? Detta är möjligt med setters. Du kan också utföra någon form av bearbetning när du hämtar värdet på en egenskap med hjälp av getters (t.ex. formatering). Ett sätt att implementera getters och setters är att använda metoder, som i Java. Sedan ES5 har vi dock ett mycket elegantare och mer praktiskt alternativ tillgängligt genom att använda syntaxen get
och set
. Då sätter vi igång!
I JavaScript är objekt samlingar av egenskaper och du har förmodligen använt dem för att lagra data tidigare. En egenskap är helt enkelt ett nyckel-värdepar. Här är ett exempel:
const options = {
timeout: 5000,
retries: 3,
ip: '192.168.1.20',
port: 4001,
};
Förmågor i ett objekt kan enkelt ställas in och läsas, så här:
artist.name = 'Carice Anouk van Houten';console.log(artist.name); //=> "Carice Anouk van Houten"
Även detta är definitivt inget nytt om du redan har viss erfarenhet av JavaScript. För att göra skillnad mellan dessa vanliga egenskaper och den andra typen som vi kommer att se i den här artikeln kan vi kalla de förstnämnda för ”dataegenskaper”.
Getters och setters: det gamla sättet
För ES5 var det enda sättet att implementera getters och setters genom att använda vanliga metoder. Som i exemplet nedan:
Jag har behållit nyckelordet function i exemplet ovan för att klargöra att det inte finns någon magi här. Endast vanliga metoder. Vi hade kunnat uppnå samma effekt genom att använda ES2015:s syntax för metoddefinitioner, som är kortare och något mer elegant:
const config = {
_port: 4001,
setPort(port) {
// ...
},
getPort() {
// ...
},
};
Användningen av den här typen av getters och setters är ganska enkel:
config.setPort(8080);
console.log(config.getPort()); //=> 8080
Inkrementering av ett värde skulle göras så här:
item.setQuantity(item.getQuantity() + 1);
Vad som ser riktigt utförligt ut jämfört med att inkrementera en egenskap direkt:
item.quantity += 1;
// Or even simpler...
item.quantity++;
Getters och setters: varför?
I OO-språk som Java, C++ eller C# är det möjligt att exponera medlemmarna i en klass på olika nivåer genom att använda åtkomstmodifierare (t.ex. public
, protected
och private
). Detta tjänar till att implementera ett viktigt koncept inom OOP som kallas dataskydd.
En mycket vanlig användning av getters och setters i dessa språk är att exponera medlemmar i en klass på ett säkert sätt. Du kan till exempel implementera endast en getter för att se till att en privat medlem aldrig kan ändras utanför klassen. En setter kan i sin tur användas för att validera de levererade värdena och bevara integriteten hos instanser av den klassen.
Hur är det med JavaScript?
I JavaScript är saker och ting lite annorlunda. När den här artikeln skrevs fanns det inga accessmodifierare i JS. För närvarande är det bästa alternativet vi har att använda symboler, som ger oss en viss nivå av sekretess när de används som nycklar. Vissa människor tycker dock inte om dem. Särskilt eftersom det är lätt att bryta denna integritet genom att använda reflection.
Jag anser inte att detta är ett verkligt problem eftersom språk som har reflection vanligtvis tillåter programmerare att bryta inkapslingen på något sätt. Problemet som jag ser med symboler är att de inte är så praktiska att använda som en enkel privat accessor skulle vara. Den goda nyheten är att ett EcmaScript-förslag som inkluderar privata fält redan befinner sig i steg 3. Och de kommer att vara immuna mot alla former av reflektion.
I exemplet i föregående avsnitt använde vi inte symboler eller något annat trick för att simulera en privat medlem. Egenskapen _port
har inget speciellt i sig självt. Det är bara en vanlig dataegenskap och som sådan kan den sättas eller läsas direkt, helt utan att använda getter och setter som vi har skapat.
Då det inte är syftet med den här artikeln att förklara symboler och andra kapslingstekniker, implementerar jag inte privata egenskaper i dess kodexempel. Kom bara ihåg att getters och setters ofta (men inte alltid) används för att ge tillgång till inkapslade medlemmar. Observera slutligen understrykningen före namnet på egenskapen _port
. Det är en de facto-konvention bland JS-utvecklare som anger att en viss egenskap är privat och att den inte bör nås utanför den klass där den är definierad.
Getters och setters: det nya sättet med accessor properties
Accessor properties är det moderna sättet att definiera getters och setters. När det gäller deras definition skiljer de sig inte så mycket från vårt tidigare exempel, men det är deras användning som verkligen är annorlunda. Låt oss först anpassa vår kod så att den använder accessor properties:
Som du kan se är det bara två saker som har ändrats i det här exemplet:
- Istället för att ha
setPort
ochgetPort
metoder. Vi använder syntaxenset
ochget
tillsammans med ett enda namn för egenskapen (”port
”, i det här exemplet) - Vi behöver inte nyckelordet
function
här. Faktum är att om du försöker använda det får du ett SyntaxError.
Hur använder man accessor properties?
Om definitionen av en accessor property är ganska lik hur vi skapar getters och setters av den gamla skolan, så har användningen av dem ingen synlig skillnad från hur vi använder vanliga dataegenskaper:
config.port = 8080;
console.log(config.port); //=> 8080
Och så här ser ett inkrementuttryck ut:
timer.seconds += 1;
Ja. Det är så enkelt. =)
Slutsats
- Objekt är samlingar av egenskaper
- En vanlig egenskap är bara ett nyckel-värdepar och kan kallas ”dataegenskap”
- Du kan implementera getters och setters som vanliga metoder. Detta är det ”gamla skolans” sätt att göra det i JavaScript.
- Getters och setters används normalt för att ge tillgång till privata medlemmar i en klass.
- Accessor properties kan bete sig precis som gamla vanliga metodbaserade getters och setters, men deras användning är utformad för att få dem att se ut som dataegenskaper.
Vill du behärska JavaScript?? Jag rekommenderar Moshs JavaScript-kurser.
Och om du gillade den här artikeln, dela den med andra också!