Ultimate Guide to Getters and Setters in JavaScript
getters og settere er funksjoner eller metoder som brukes til få og sett Verdiene av variabler. Getter-setter-konseptet er vanlig i dataprogrammering: nesten alle høyt programmeringsspråk kommer med et sett med syntaks for å implementere getters og setters, inkludert JavaScipt.
I dette innlegget vil vi se hva getters setters er, og hvordan opprett og bruk dem i JavaScript.
Getters-setters and encapsulation
Ideen om getters og setters er alltid nevnt i forbindelse med innkapsling. Innkapsling kan være forstått på to måter.
For det første er det oppsettet av data-Getters settere trio for å få tilgang til og modifisere dataene. Denne definisjonen er nyttig når noen operasjoner, for eksempel validering, må være utført på dataene før du lagrer eller ser på det-gettere og settere gir det perfekte hjem for det.
For det andre er det en strengere definisjon i henhold til hvilken innkapsling gjøres skjul data, for å gjøre det utilgjengelig fra annen kode, unntatt gjennom getters og setters. På denne måten slutter vi ikke ved et uhell overskrive viktige data med noen annen kode i programmet.
Opprett getters og setters
1. Med metoder
Siden getters og setters er i utgangspunktet funksjoner som henter / endrer en verdi, er det mer enn én måte å opprette og bruke dem. Den første måten er:
var obj = foo: 'dette er verdien av foo', getFoo: function () return this.foo; , setFoo: funksjon (val) this.foo = val; console.log (obj.getFoo ()); // "dette er verdien av foo" obj.setFoo ('hei'); console.log (obj.getFoo ()); // "Hallo"
Dette er den enkleste måten å skape getters og setters. Det er en eiendom foo
og det er to metoder: getFoo
og setFoo
til returnere og tilordne en verdi til den eiendommen.
2. med søkeord
En mer “offisielt” og robust måte å skape getters og setters på er å bruke få
og sett
søkeord.
Til skape en getter, plasser få
søkeord foran en funksjonsdeklarasjon som vil tjene som getter-metoden, og bruk sett
søkeord på samme måte som lag en setter. Syntaxen er som følger:
var obj = fooVal: 'dette er verdien av foo', få foo () return this.fooVal; , sett foo (val) this.fooVal = val; console.log (obj.foo); // "dette er verdien av foo" obj.foo = 'hei'; console.log (obj.foo); // "Hallo"
Vær oppmerksom på at dataene bare kan være lagret under et eiendomsnavn (fooVal
) det er forskjellig fra navnet på getter-setter-metodene (foo
) fordi en eiendom som holder getter-setteren kan ikke holde dataene også.
Hvilken vei er bedre?
Hvis du velger å lage getters og setters med søkeord, kan du bruke oppdragsoperatør for å stille inn dataene og dot operator for å få dataene, På samme måte som du vil få tilgang til / angi verdien av en vanlig eiendom.
Men hvis du velger den første måten å kode getters og settere, må du ringe setter og getter-metodene ved hjelp av funksjonssamtalen syntaks fordi de er typiske funksjoner (ikke noe spesielt som de som er opprettet ved hjelp av få
og sett
søkeord).
Det er også en sjanse for at du kan ende opp ved et uhell tildele noen annen verdi til egenskapene som holdt disse getter-setter metoder og miste dem helt! Noe du ikke trenger å bekymre deg om i den senere metoden.
Så, du kan se hvorfor jeg sa Andre teknikker er mer robuste.
Overskriveforebygging
Hvis du av en eller annen grunn foretrekker den første teknikken, gjør egenskapene med getter-setter-metodene skrivebeskyttet ved å skape dem ved hjelp av Object.defineProperties
. Egenskaper opprettet via Object.defineProperties
, Object.defineProperty
og Reflect.defineProperty
konfigurer automatisk til skrivbar: false
som betyr skrivebeskyttet:
/ * Overskrivningsforebygging * / var obj = foo: 'dette er verdien av foo'; Object.defineProperties (obj, 'getFoo': verdi: funksjon () return this.foo;, 'setFoo': verdi: funksjon (val) this.foo = val;); obj.getFoo = 66; // getFoo kommer ikke til å bli overskrevet! console.log (obj.getFoo ()); // "dette er verdien av foo"
Operasjoner inne getters og setters
Når du har introdusert getters og setters, kan du gå videre og utføre operasjoner på dataene før du endrer eller returnerer den.
I koden under, i getter-funksjonen er dataene sammenkuttet med en streng før den returneres, og i setter-funksjonen en validering av om verdien er et tall eller ikke utføres før oppdatering n
.
var obj = n: 67, få id () return 'ID er:' + this.n; , sett id (val) if (typeof val === 'tall') this.n = val; console.log (obj.id); // "ID er: 67" obj.id = 893; console.log (obj.id); // "IDen er: 893" obj.id = 'hei'; console.log (obj.id); // "IDen er: 893"
Beskytt data med getters og setters
Så langt har vi dekket bruk av getters og settere i den første sammenhengen av innkapsling. La oss gå videre til det andre, det vil si hvordan skjul data fra utenfor kode ved hjelp av getters og setters.
Ubeskyttede data
Opprettelsen av getters og setters betyr ikke at dataene kun kan nås og endres via disse metodene. I det følgende eksemplet er det endret direkte uten å berøre getter og setter metoder:
var obj = fooVal: 'dette er verdien av foo', få foo () return this.fooVal; , sett foo (val) this.fooVal = val; obj.fooVal = 'hei'; console.log (obj.foo); // "Hallo"
Vi brukte ikke setteren, men direkte endret dataene (fooVal
). Dataene vi opprinnelig satt inne obj
er borte nå! For å forhindre at dette skjer (ved et uhell), gjør du det trenger litt beskyttelse for dine data. Du kan legge til det ved begrenser omfanget av hvor dataene dine er tilgjengelige. Du kan gjøre det ved enten blokkere omfanget eller funksjonsomfang.
1. Blokker scoping
En måte er å bruk en blokk rekkevidde innenfor hvilke dataene vil bli definert ved hjelp av la
søkeord som begrenser omfanget til den blokken.
EN blokkere omfang kan opprettes ved å plassere koden din inne i et par krøllete braces. Når du lager et blokkeringsområde, sørg for å Legg igjen en kommentar over det som ber om braces å være alene, slik at ingen fjerner bøylene ved en feil tenker de er noen ekstra overflødige braces i koden eller legg til en etikett til blokkeringsområdet.
/ * BLOCK SCOPE, la armlene alene! * / let fooVal = 'dette er verdien av foo'; var obj = get foo () return fooVal; , sett foo (val) fooVal = val fooVal = 'hallo'; // ikke kommer til å påvirke fooVal inne i block console.log (obj.foo); // "dette er verdien av foo"
Endring / oppretting fooVal
utenfor blokken vil ikke påvirke de fooVal
referert inne i getters setters.
2. Funksjonsomfang
Den mer vanlige måten å beskytte dataene med scoping på er at holder dataene inne i en funksjon og returnerer et objekt med getters og setters fra den funksjonen.
funksjon myobj () var fooVal = 'dette er verdien av foo'; return get foo () return fooVal; , sett foo (val) fooVal = val fooVal = 'hallo'; // ikke kommer til å påvirke vår opprinnelige fooVal var obj = myobj (); console.log (obj.foo); // "dette er verdien av foo"
Objektet (med foo ()
getter-setter innsiden av den) returnert av myObj ()
funksjonen er lagret i obj
, og så obj
er vant til ring til getter og setter.
3. Databeskyttelse uten omfang
Det er også en annen måte at du kan beskytte dataene dine fra å bli overskrevet uten å begrense omfanget. Logikken bak den går slik: Hvordan kan du endre et datatyper hvis du ikke vet hva som kalles?
Hvis dataene har a ikke så lett reproduserbar variabel / eiendomsnavn, sjansene er at ingen (selv oss selv) kommer til å ende opp med å overskrive den ved å tildele noen verdi til den variabelen / eiendomsnavnet.
var obj = s89274934764: 'dette er verdien av foo', få foo () return dette.s89274934764; , sett foo (val) this.s89274934764 = val; console.log (obj.foo); // "dette er verdien av foo"
Se, det er en måte å jobbe på. Selv om navnet jeg valgte ikke er veldig bra, kan du også bruk tilfeldige verdier eller symboler å skape eiendomsnavn som det er foreslått av Derick Bailey i dette blogginnlegget. Hovedmålet er å hold dataene skjulte fra annen kode og la et getter-setter-par få tilgang til / oppdatere den.
Når skal du bruke getters og setters?
Nå kommer det store spørsmålet: begynner du å tildele getters og setters til alle dine data nå?
Hvis du er gjemmer data, så er det ikke noe annet valg.
Men hvis dataene dine blir sett av annen kode, er det greit, trenger du fortsatt å bruke gettersettere bare for å pakke det opp med kode som utfører noen operasjoner på det? jeg ville ha sagt ja. Kode legger opp veldig snart. Opprette mikroenheter av individuelle data med sin egen getter-setter gir deg en viss uavhengighet å jobbe med dataene uten å påvirke andre deler av koden.