încapsulare în JavaScript

aceasta va fi ultima mea postare din seria „JavaScript pentru dezvoltatorii (C/)AL” astăzi. Dacă am continuat blogging-ul despre chestii JavaScript aproape pur, ai putea întreba în mod rezonabil dacă acest lucru este, de fapt, un blog NAV sau unul JavaScript. Este încă NAV și, în timp ce lucrurile despre care urmează să scriu sunt pur și simplu un concept JavaScript, mi se pare extrem de relevant pentru orice dezvoltator de suplimente de control. Așa că, ține-mi berea și așteaptă încă una.

una dintre plângerile pe care le aud adesea despre JavaScript este că în JavaScript nu există încapsulare. Acest lucru este aproape complet adevărat, cu excepția faptului că este în întregime fals.

unde este problema în primul rând și apoi care este soluția? Să ne scufundăm.

problema

Imaginați-vă că declarați un constructor. Imaginați-vă pentru o secundă că suntem în lumea ES5 (pe care, din păcate, trebuie să o folosim dacă dorim ca add-in-urile noastre de control să fie pe deplin compatibile cu toate platformele pe care sunt acceptate atât NAV, cât și Business Central).

acesta este codul meu:

evident, acest lucru arată 42, care este vârsta mea actuală.

în curând, va fi ziua mea de naștere, așa că acest lucru ar arăta 43:

acum, în timp ce mi-ar plăcea absolut să pot face așa ceva în viața reală:

… asta nu se va întâmpla. Într-o lume decentă orientată pe obiecte, „vârsta” ar trebui să fie o proprietate încapsulată și nu ar trebui să poți apela vjeko.vârsta = 25 la toate. C # și limbajele orientate pe obiecte „normale” au un concept de încapsulare, se pot ocupa de acest lucru folosind câmpuri private, dar JavaScript nu are niciun concept de privat. Orice lucru definit în interiorul constructorului de obiecte (sau mai târziu pe o instanță a unui obiect construit) este pe deplin accesibil tuturor codurilor care au acces la acea instanță. În exemplul meu de mai sus, oricine poate stabili vârsta și să scape cu ea.

ai putea spune că JavaScript nu are încapsulare. Și, așa cum am spus mai sus, te-ai înșela complet.

soluția

pe cât de evident este că nu putem declara nimic ca privat direct, există încă lucruri pe care le putem folosi. Un concept frumos care vine la îndemână se numește închideri. Închiderile sunt explicate pe larg pe un milion de bloguri, site-uri de documentare și exemple de coduri pe tot internetul și puteți căuta pe Google bejesus din ele în ritmul propriu, așa că nu voi aprofunda explicarea închiderilor aici. Voi sări pur și simplu direct în aplicarea lor pentru rezolvarea problemei de încapsulare.

există cel puțin două moduri în care puteți gestiona acest lucru. Să facem mai întâi cea mai evidentă: o funcție de acces.

Imaginați-vă lumea fără proprietăți în care nu puteți obiecta.proprietate = valoare (cum ar fi vjeko.vârsta = 25 în cazul nostru, la fel de mult ca mi-ar plăcea total!). În acea lume, ai avea funcții getter și setter:

(ignorați pentru o clipă faptul că încă folosesc acest lucru.vârsta pentru a „încapsula „”proprietatea”)

evident, ați putea să le numiți astfel:

apoi, dacă doriți să aveți vârsta ca read-only, pur și simplu renunțați la funcția setAge setter. Dacă asta.vârsta a fost într-adevăr privată (ceea ce nu este), acest lucru ar face truc pentru tine. Problema este, nimic definit pe acest lucru este privat, este accesibil pentru oricine are acces la orice instanță a obiectului. E cât se poate de public.

pentru a rezolva această problemă, primul lucru pe care trebuie să-l facem este să mutăm declarația funcției getter de la prototip la instanță. Membrii prototipului sunt cei mai apropiați de ceea ce am numi static în C#, chiar dacă în timpul rulării au anumite trăsături comportamentale atât ale membrilor statici, cât și ale instanțelor. Cu toate acestea, să mutăm mai întâi membrul departe de prototip și pe instanță:

aceasta rezolvă doar prima parte a problemei, faptul că getAge a fost definit mai degrabă pe prototip decât pe instanță. Cu toate acestea, cu o schimbare simplă ca aceasta:

… rezolvăm problema în întregime:

vârsta este acum complet încapsulată. Îl puteți accesa prin funcția getter, dar nu îl puteți seta direct, deoarece este accesibil doar în domeniul de închidere al acestui.funcția de instanță getAge.

pentru a implementa complet clasa persoană, trebuie să mutați funcția growOlder din prototip în instanță:

și acest lucru funcționează exact așa cum doriți să funcționeze:

dar de ce funcționează? Funcționează din cauza închiderilor. Parametrul de vârstă de la constructor a fost capturat în sfera de închidere a funcțiilor getAge și growOlder, permițându-vă să accesați valoarea sa din ambele funcții, dar făcându-l complet inaccesibil pentru oricine altcineva, oriunde altundeva.

soluție chiar mai bine

ai putea spune că nu doriți să-l acceseze printr-o funcție getter, și că aveți nevoie de sintaxa de proprietate numai în citire în plină floare. Vrei vârsta ta read-only și încapsulate în același timp. Te-am prins! JavaScript nu poate încapsula asta! Cu excepția faptului că este absolut posibil.

am abordat obiectul.definimetoda de proprietate în postarea mea anterioară și, dacă o citiți, puteți vedea imediat cum poate fi aplicată aici.

deci, să definim o proprietate instanță numai în citire de clasă persoană:

acolo. Nu m-a durut. Și funcționează:

deci, nu-l ai. Încapsulare completă în JavaScript pentru a vă ajuta să scrieți un cod bun, izolat și să vă luați suplimentele de control la nivelul real kick-a$$.

Javascripting fericit, și sper pentru a obține mai mult timp pentru a blog despre alte sfaturi și trucuri interesante și utile JavaScript pentru dezvoltatori (C/)AL.

Lasă un răspuns

Adresa ta de email nu va fi publicată.