indkapsling i JavaScript

dette bliver mit sidste indlæg i serien “JavaScript for (C/)Al Developers” i dag. Hvis jeg fortsatte med at blogge om næsten rene JavaScript-ting, kunne du med rimelighed spørge, om dette faktisk er en NAV-blog eller en JavaScript-blog. Det er stadig NAV, og mens de ting, jeg er ved at skrive om, er rent et JavaScript-koncept, finder jeg det meget relevant for enhver kontrol-tilføjelsesudvikler. Så, hold min øl, og bære med mig for en anden.

en af de klager, jeg ofte hører om JavaScript, er, at der i JavaScript ikke er nogen indkapsling. Dette er næsten helt sandt, bortset fra at det er helt falsk.

hvor er problemet i første omgang, og hvad er så løsningen? Lad os dykke ind.

problemet

Forestil dig, at du erklærer en konstruktør. Forestil dig et øjeblik, at vi er i ES5-verdenen (som vi desværre skal bruge, hvis vi ønsker, at vores kontroludvidelser skal være fuldt kompatible med alle platforme, hvor både NAV og Business Central understøttes).

dette er min kode:

naturligvis, dette viser 42, hvilket er min nuværende alder.

snart bliver det min fødselsdag, så dette ville vise 43:

nu, mens jeg absolut ville elske at kunne gøre noget som dette i det virkelige liv:

… det kommer ikke til at ske. I en anstændig objektorienteret verden bør” alder ” være en indkapslet ejendom, og du bør ikke kunne ringe til vjeko.Alder = 25 overhovedet. C# og” normale ” objektorienterede sprog har et begreb om indkapsling, de kan håndtere dette ved hjælp af private felter, men JavaScript har intet begreb om privat. Alt defineret på dette inde i objektkonstruktøren (eller senere på en forekomst af et konstrueret objekt) er fuldt tilgængeligt for al kode, der har adgang til den forekomst. I mit eksempel ovenfor, alle kan indstille alder og slippe af sted med det.

man kan sige, at JavaScript ikke har nogen indkapsling. Og som jeg sagde ovenfor, ville du være helt forkert.

løsningen

så indlysende som det er, at vi ikke kan erklære noget som privat direkte, er der stadig ting, vi kan bruge. Et smukt koncept, der er praktisk, kaldes lukninger. Lukninger forklares udførligt på en million blogs, dokumentationssider og kodeeksempler over hele internettet, og du kan google bejesus ud af dem i dit eget tempo, så jeg vil ikke dykke ned i at forklare lukninger her. Jeg hopper simpelthen lige ind i at anvende dem til at løse indkapslingsproblemet.

der er mindst to måder, hvordan du kan håndtere dette. Lad os først gøre det mere indlysende: en adgangsfunktion.

Forestil dig verden uden egenskaber, hvor du ikke kan gøre indsigelse.ejendom = værdi (ligesom vjeko.Alder = 25 i vores tilfælde, så meget som jeg helt ville elske det!). I den verden ville du have getter og setter funktioner:

(Ignorer et øjeblik det faktum, at jeg stadig bruger dette.”indkapsle “”egenskaben”)

det er klart, at du kan kalde disse sådan:

derefter, hvis du ville have alder som skrivebeskyttet, ville du blot droppe setAge setter-funktionen. Hvis dette.alder var virkelig privat (som det ikke er), dette ville gøre tricket for dig. Problemet er, intet defineret på dette er privat, det er tilgængeligt for alle, der har adgang til nogen forekomst af objektet. Det er så offentligt, som det bliver.

for at løse dette problem er det første, vi skal gøre, at flytte getter-funktionserklæringen fra prototypen til forekomsten. Prototype medlemmer er tættest på det, vi ville kalde statisk i C#, selvom de i runtime har visse adfærdsmæssige træk hos både statiske og instansmedlemmer. Imidlertid, lad os først flytte medlemmet væk fra prototypen, og på instans:

dette løser kun den første del af problemet, det faktum, at getAge blev defineret på prototypen snarere end på forekomsten. Men med en simpel ændring som denne:

… vi løser problemet helt:

alder er nu fuldt indkapslet. Du kan få adgang til det via getter-funktionen, men du kan ikke indstille det direkte, fordi det kun er tilgængeligt i lukningsområdet for dette.getAge instans funktion.

for fuldt ud at implementere Personklassen skal du flytte vækstfunktionen fra prototypen til forekomsten:

og dette fungerer nøjagtigt som du vil have det til at fungere:

men hvorfor virker det? Det virker på grund af lukninger. Aldersparameteren fra konstruktøren blev fanget i lukningsområdet for både getAge-og vækstfunktionerne, så du kan få adgang til dens værdi fra begge disse funktioner, men gør det helt utilgængeligt for nogen anden, andre steder.

endnu bedre løsning

du kan sige, at du ikke ønsker at få adgang til det via en getter-funktion, og at du har brug for fuldblæst skrivebeskyttet egenskabssyntaks. Du vil have din alder skrivebeskyttet og indkapslet på samme tid. Fik dig! JavaScript kan ikke indkapsle det! Bortset fra at det absolut kan.

jeg adresserede objektet.defineProperty metode i mit tidligere indlæg, og hvis du læser den ene, kan du straks se, hvordan den kan anvendes her.

så lad os definere en skrivebeskyttet instansegenskab for Personklasse:

der. Det gjorde ikke ondt. Og det virker:

så der har du det. Fuldblæst indkapsling i JavaScript for at hjælpe dig med at skrive god, isoleret kode og tage dine kontroludvidelser til ægte kick-A$$ niveau.

glad JavaScripting, og jeg håber at få mere tid til at blogge om andre seje og nyttige JavaScript tips og tricks til (C/)al udviklere.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.