Jack Franklin

December 23, 2013

A JavaScriptben többnyire azt kapod, amit látsz. Az érték az érték, nincsenek trükkök. Néha azonban olyan értéket akarsz, amely más értékeken alapul: valakinek a teljes neve például a kereszt- és vezetéknevének az összevonásából áll. Ha van egy person objektumod, és azt akarod, hogy az objektum felhasználói beállíthassák a teljes, kereszt- vagy vezetéknevet, és a változás azonnal tükröződjön a többi értékben, akkor ezt konvencionálisan függvényekkel építenéd fel:

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

De ez csúnya, és megköveteli, hogy az objektumod felhasználói törődjenek azzal, hogy a tulajdonságok kapcsolatban vannak egymással; egy összetettebb példában ez nem biztos, hogy olyan nyilvánvaló, mint a nevek esetében. Szerencsére van egy jobb módszer, amely az ECMAScript 5-ben került bele.

Találkozzunk a getterekkel és setterekkel.

Hogyan

Készítsük el azt a személy objektumot. Szeretnénk, ha beállíthatnánk a keresztnevet, a vezetéknevet vagy a teljes nevet, és a másik kettőt automatikusan frissítené.

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

Mi történik itt?

A get és set kulcsszavak fontosak. Utánuk következik a tulajdonság, amelyre vonatkoznak (fullName) és egy függvénytest, amely meghatározza a viselkedést a tulajdonság elérésekor (name = person.fullName) vagy módosításakor (person.fullName = 'Some Name').

Ez a két kulcsszó hozzáférési függvényeket definiál: egy getter és egy setter a fullName tulajdonsághoz. A tulajdonság elérésekor a getter visszatérési értéke kerül felhasználásra. Az érték beállításakor a setter meghívásra kerül, és a beállított értéket adja át. Rajtad múlik, hogy mit kezdesz ezzel az értékkel, de a setter által visszaadott érték az átadott érték – tehát nem kell semmit sem visszaadnod.

A hivatalos út: Object.defineProperty

A getterek és setterek deklarálásának inline módszere mellett explicit módon is megtehetjük Object.defineProperty (MDN dokumentáció). Ez a módszer három argumentumot fogad el. Az első a tulajdonságot hozzáadni kívánt objektum, a második a tulajdonság neve, a harmadik pedig a tulajdonságot leíró objektum (az úgynevezett tulajdonság leírója). Íme egy példa, amely megismétli a fenti példát:

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 || '';}});

Az előny itt nem látszik azonnal. Azon kívül, hogy a kezdeti objektum létrehozása után tudunk tulajdonságokat hozzáadni, van-e valódi előnye?

Ha így definiálunk egy tulajdonságot, sokkal többet tehetünk, mint egy setter vagy getter definiálása. A következő kulcsokat is átadhatjuk:

  • configurable (alapértelmezés szerint false): ha ez igaz, akkor a tulajdonság beállítása a jövőben módosítható lesz.
  • enumerable (alapértelmezés szerint false): ha igaz, akkor a tulajdonság megjelenik az objektumon való átfutáskor (for (var key in obj)).

Meghatározhatunk olyan tulajdonságokat is, amelyeknek nincs explicit getterük vagy setterük:

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

Ez létrehozza a person.age tulajdonságot, és a 42-es értékre állítja. Fontos megjegyezni, hogy ez a tulajdonság nem írható. A person.age = 99 meghívásának nincs hatása. Ily módon csak olvasható tulajdonságokat hozhatunk létre. Ha egy tulajdonságnak value kulcs van beállítva, akkor nem lehet gettere vagy settere. A tulajdonságoknak csak értékei vagy hozzáférői lehetnek, mindkettő nem.

Nem csak ez, hanem mivel a enumerable tulajdonság alapértelmezett értéke false, ez a tulajdonság nem fog megjelenni, amikor az objektum kulcsain végighaladunk.

Ha írhatóvá akarnánk tenni egy tulajdonságot, akkor a writable tulajdonságot kellene beállítanunk:

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

Most a person.age = 99; fogja elérni a kívánt hatást.

Túlhasználat

Ne feledjük: csak azért, mert egy tulajdonság létezik, nem kell mindig használni. A Gettereknek és Settereknek megvannak a maguk felhasználási esetei, de ne essünk túlzásba, különben valószínűleg olyan dizájnnal fogunk végezni, amely zavaró az objektumokkal interakcióba lépők számára. Óvatosan használva nagyon erősek. De a nagy hatalommal nagy felelősség is jár.

Böngészőtámogatás?

Az IE9 és a magasabb verziószámok teljes mértékben támogatják a Object.defineProperty, valamint a Safari 5+, Firefox 4+, Chrome 5+ és Opera 12+. Ha Node.js-szel dolgozol, akkor teljes támogatás van. Hát nem imádod a Node-ot?!”

Ez a cikk Tom Ashworth-tal közösen íródott. Köszönöm Tomnak a segítségét az összeállításban.

Ha tetszett ez a bejegyzés, iratkozz fel a hírlevélre, hogy értesülj az új tartalmakról 😎.

Minden blogbejegyzés

Ha tetszett ez a bejegyzés, kövess engem a Twitteren.

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.