Jack Franklin

Decembrie 23, 2013

În cea mai mare parte, în JavaScript, ceea ce vezi este ceea ce primești. O valoare este o valoare; nu există trucuri. Uneori, însă, doriți o valoare care se bazează pe alte valori: numele complet al cuiva, de exemplu, este o concatenare a numelui și prenumelui său. Dacă aveți un obiect person și doriți ca utilizatorii acelui obiect să poată seta numele complet, prenumele sau numele de familie și să vadă această modificare reflectată imediat în celelalte valori, în mod convențional l-ați construi cu ajutorul funcțiilor:

person.setLastName('Smith');person.setFirstName('Jimmy');person.getFullName(); // Jimmy Smith

Dar acest lucru este urât și necesită ca utilizatorilor obiectului dumneavoastră să le pese că proprietățile sunt legate între ele; într-un exemplu mai complex, acest lucru ar putea să nu fie la fel de evident ca în cazul numelor. Din fericire, există o modalitate mai bună, adăugată în ECMAScript 5.

Întâlnim getteri și setteri.

Cum

Să facem acel obiect persoană. Vrem să putem seta numele, prenumele, numele de familie sau numele complet și să le actualizăm automat pe celelalte două.

var person = { firstName: 'Jimmy', lastName: 'Smith', get fullName() { return this.firstName + ' ' + this.lastName; }, set fullName (name) { var words = name.toString().split(' '); this.firstName = words || ''; this.lastName = words || ''; }}

person.fullName = 'Jack Franklin';console.log(person.firstName); // Jackconsole.log(person.lastName) // Franklin

Și ce se întâmplă aici?

Cuvintele cheie get și set sunt importante. După ele urmează proprietatea la care se referă (fullName) și un corp de funcție care definește comportamentul atunci când proprietatea este accesată (name = person.fullName) sau modificată (person.fullName = 'Some Name').

Aceste două cuvinte cheie definesc funcții accesor: un getter și un setter pentru proprietatea fullName. Atunci când proprietatea este accesată, se utilizează valoarea de întoarcere de la getter. Atunci când se stabilește o valoare, setterul este apelat și i se transmite valoarea care a fost stabilită. Depinde de dvs. ce faceți cu acea valoare, dar ceea ce se returnează de la setter este valoarea care a fost transmisă – deci nu trebuie să returnați nimic.

Metoda oficială: Object.defineProperty

Pe lângă metoda inline de declarare a getterilor și setterilor, se poate face, de asemenea, mai explicit prin Object.defineProperty (documentația MDN). Această metodă primește trei argumente. Primul este obiectul la care se adaugă proprietatea, al doilea este numele proprietății, iar al treilea este un obiect care descrie proprietatea (cunoscut sub numele de descriptor al proprietății). Iată un exemplu care reproduce exemplul de mai sus:

var person = { firstName: 'Jimmy', lastName: 'Smith'};

Object.defineProperty(person, 'fullName', {get: function() {return firstName + ' ' + lastName;},set: function(name) {var words = name.split(' ');this.firstName = words || '';this.lastName = words || '';}});

Avantajul de aici nu este imediat evident. În afară de posibilitatea de a adăuga proprietăți după crearea obiectului inițial, există vreun beneficiu real?

Când definiți o proprietate în acest mod, puteți face mult mai mult decât să definiți un setter sau getter. De asemenea, puteți trece următoarele chei:

  • configurable (false în mod implicit): dacă este adevărat, configurația proprietății va putea fi modificată în viitor.
  • enumerable (false în mod implicit): dacă este adevărat, proprietatea va apărea atunci când se face o buclă peste obiect (for (var key in obj)).

De asemenea, putem defini proprietăți care nu au getteri sau setteri expliciți:

Object.defineProperty(person, 'age', { value: 42});

Aceasta va crea person.age și o va seta la valoarea 42. Este important să rețineți că această proprietate nu este inscriptibilă. Apelarea person.age = 99 nu va avea nici un efect. În acest fel, puteți crea proprietăți numai pentru citire. În cazul în care o proprietate are setată o cheie value, aceasta nu poate avea un getter sau setter. Proprietățile pot avea valori sau accesori, nu ambele.

Nu numai atât, dar pentru că proprietatea enumerable are valoarea implicită false, această proprietate nu va apărea atunci când vom face o buclă peste cheile obiectului.

Dacă am fi vrut să facem o proprietate inscriptibilă, ar fi trebuit să setăm proprietatea writable:

Object.defineProperty(person, 'age', { value: 42, writable: true});

Acum, person.age = 99; va avea efectul dorit.

Utilizare excesivă

Amintiți-vă: doar pentru că o caracteristică există, nu trebuie să fie folosită tot timpul. Getters și Setters au cazurile lor de utilizare, dar nu exagerați, sau cel mai probabil veți sfârși cu un design care este confuz pentru cei care interacționează cu obiectele dvs. Folosite cu atenție, acestea sunt foarte puternice. Dar cu o mare putere vine și o mare responsabilitate.

Suport pentru browsere?

IE9 și versiunile superioare au suport complet pentru Object.defineProperty, împreună cu Safari 5+, Firefox 4+, Chrome 5+ și Opera 12+. Dacă lucrați cu Node.js, există suport complet. Nu-i așa că vă place Node?!

Acest articol a fost scris împreună cu Tom Ashworth. Îi mulțumim lui Tom pentru tot ajutorul acordat la alcătuirea acestui articol.

Dacă v-a plăcut acest articol, înscrieți-vă la newsletter pentru a primi actualizări cu conținut nou 😎.

Toate articolele de pe blog

Dacă v-a plăcut acest articol, nu uitați să mă urmăriți pe Twitter.

Lasă un răspuns

Adresa ta de email nu va fi publicată.