Innkapsling I JavaScript

Dette blir mitt siste innlegg i» JavaScript FOR (C/)Al Developers » – serien i dag. Hvis jeg fortsatte å blogge om nesten rene JavaScript-ting, kan du med rimelighet spørre om dette faktisk er EN NAV-blogg eller En JavaScript-en. Det er FORTSATT NAV, og mens ting jeg skal skrive om, er rent Et JavaScript-konsept, finner jeg det svært relevant for enhver kontrolltilleggutvikler. Så hold ølet mitt, og bær med meg for en annen.

En av klagerne jeg ofte hører Om JavaScript er At I JavaScript er det ingen innkapsling. Dette er nesten helt sant, bortsett fra det faktum at det er helt feil.

Hvor er problemet i utgangspunktet,og hva er løsningen? La oss dykke inn.

problemet

Tenk deg at du erklærer en konstruktør. Tenk deg for et sekund at VI er I ES5 verden (som vi dessverre må bruke hvis vi vil at våre kontrolltillegg skal være fullt kompatible med alle plattformer som BÅDE NAV og Business Central støttes på).

Dette er koden min:

Åpenbart, dette viser 42, som er min nåværende alder.

snart blir det bursdagen min, så dette ville vise 43:

Nå, mens jeg absolutt ville elske å kunne gjøre noe slikt i det virkelige liv:

… det kommer ikke til å skje. I en anstendig objektorientert verden bør «alder» være en innkapslet eiendom, og du bør ikke kunne ringe vjeko.alder = 25 i det hele tatt. C# og» normale » objektorienterte språk har et konsept for innkapsling, de kan håndtere dette ved hjelp av private felt, Men JavaScript har ikke noe begrep om privat. Alt som er definert på dette inne i objektkonstruktøren (eller senere på en forekomst av et konstruert objekt) er fullt tilgjengelig for all kode som har tilgang til den forekomsten. I mitt eksempel ovenfor kan alle sette alder og komme unna med det.

Du kan si At JavaScript ikke har noen innkapsling. Og som jeg sa ovenfor, ville du være helt feil.

løsningen

så åpenbart som det er at vi ikke kan erklære noe som privat direkte, er det fortsatt ting vi kan bruke. Et vakkert konsept som kommer til nytte kalles nedleggelser. Nedleggelser forklares lenge på en million blogger, dokumentasjonssider og kodeeksempler over hele internett, og du kan google bejesus ut av dem i ditt eget tempo, så jeg vil ikke dykke inn i å forklare nedleggelser her. Jeg vil bare hoppe rett inn i å bruke dem til å løse innkapslingsproblemet.

det er minst to måter hvordan du kan håndtere dette. La oss først gjøre det mer åpenbare: en tilgangsfunksjon.

Forestill deg verden uten egenskaper der du ikke kan gjøre objekt.eiendom = verdi (som vjeko.alder = 25 i vårt tilfelle, så mye som jeg helt ville elske det!). I den verden vil du ha getter og setter funksjoner:

(ignorer et øyeblikk det faktum at jeg fortsatt bruker dette.alder for å «innkapsle «»egenskapen»)

Åpenbart vil du kunne ringe disse slik:

Så, hvis du ønsket å ha alder som skrivebeskyttet, ville du bare slippe setAge setter-funksjonen. Hvis dette.alder var veldig privat (som det ikke er), dette ville gjøre trikset for deg. Problemet er at ingenting definert på dette er privat, det er tilgjengelig for alle som har tilgang til enhver forekomst av objektet. Det er så offentlig som det blir.

for å fikse dette problemet, er det første vi må gjøre, å flytte getter-funksjonsdeklarasjonen fra prototypen til forekomsten. Prototypemedlemmer er nærmest det vi vil kalle statisk I C#, selv om de i kjøretid har visse atferdsegenskaper hos både statiske og instansmedlemmer. Men la oss først flytte medlemmet bort fra prototypen, og på forekomst:

dette løser bare den første delen av problemet, det faktum at getAge ble definert på prototypen i stedet for på forekomsten. Men med en enkel endring som dette:

… vi løser problemet helt:

Alder er nå fullt innkapslet. Du kan få tilgang til den via getter-funksjonen, men du kan ikke angi den direkte fordi den bare er tilgjengelig i lukkeområdet for dette.getAge forekomst funksjon.

for å fullt ut implementere Personklassen må du flytte growOlder-funksjonen fra prototypen til forekomsten:

og dette fungerer akkurat som du vil at den skal fungere:

Men hvorfor virker det? Det fungerer på grunn av nedleggelser. Alder parameter fra konstruktøren ble fanget i nedleggelse omfanget av både getAge og growOlder funksjoner, slik at du kan få tilgang til sin verdi fra begge disse funksjonene, men gjør det helt utilgjengelig for noen andre, noe annet sted.

Enda bedre løsning

Du kan si at du ikke vil ha tilgang til den gjennom en getter-funksjon, og at du trenger fullblåst skrivebeskyttet egenskapssyntaks. Du vil ha din alder skrivebeskyttet og innkapslet på samme tid. Har deg! JavaScript kan ikke kapsle det! Bortsett fra at det absolutt kan.

jeg adresserte Objektet.defineProperty-metoden i mitt forrige innlegg, og hvis du leser den, kan du umiddelbart se hvordan den kan brukes her.

Så, la oss definere en skrivebeskyttet instansegenskap For Personklasse:

Der. Det gjorde ikke vondt. Og det fungerer:

Så der har du det. Fullblåst innkapsling I JavaScript for å hjelpe deg med å skrive god, isolert kode, og ta kontrolltilleggene dine til ekte kick-a$$ nivå.

Glad JavaScripting, og jeg håper å få mer tid til å blogge om andre kule Og nyttige JavaScript tips og triks for (C/)al utviklere.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert.