Kétféle objektumtulajdonság létezik.
Az első fajta az adattulajdonságok. Már tudjuk, hogyan kell velük dolgozni. Minden tulajdonság, amit eddig használtunk, adattulajdonság volt.
A második fajta tulajdonság valami új. Ez a hozzáférési tulajdonságok. Ezek lényegében olyan függvények, amelyek egy érték megszerzésekor és beállításakor végrehajtódnak, de egy külső kód számára úgy néznek ki, mint a hagyományos tulajdonságok.
Getterek és setterek
Az accessor tulajdonságokat “getter” és “setter” metódusok képviselik. Egy objektum literálban ezeket get és set jelöli:
let obj = { get propName() { // getter, the code executed on getting obj.propName }, set propName(value) { // setter, the code executed on setting obj.propName = value }};A getter akkor működik, amikor obj.propName beolvassuk, a setter – amikor hozzárendeljük.
Egy user objektumunk van például name és surname tulajdonságokkal:
let user = { name: "John", surname: "Smith"};Most szeretnénk hozzáadni egy fullName tulajdonságot, aminek "John Smith"-nek kell lennie. Természetesen nem akarjuk a meglévő információt copy-paste módon beilleszteni, ezért megvalósíthatjuk accessorként:
let user = { name: "John", surname: "Smith", get fullName() { return `${this.name} ${this.surname}`; }};alert(user.fullName); // John SmithKívülről nézve egy accessor tulajdonság úgy néz ki, mint egy hagyományos. Ez az accessor tulajdonságok lényege. A user.fullName-ot nem függvényként hívjuk meg, hanem normálisan olvassuk: a getter a színfalak mögött fut.
A fullName-nek mostantól csak egy gettere van. Ha megpróbáljuk hozzárendelni a user.fullName=-t, hiba fog jelentkezni:
let user = { get fullName() { return `...`; }};user.fullName = "Test"; // Error (property has only a getter)Hozzuk helyre úgy, hogy a user.fullName-hoz hozzáadunk egy settert:
let user = { name: "John", surname: "Smith", get fullName() { return `${this.name} ${this.surname}`; }, set fullName(value) { = value.split(" "); }};// set fullName is executed with the given value.user.fullName = "Alice Cooper";alert(user.name); // Alicealert(user.surname); // CooperAz eredmény egy “virtuális” tulajdonság fullName lesz. Ez olvasható és írható.
Accessor leírók
A accessor tulajdonságok leírói különböznek az adat tulajdonságoktól.
A accessor tulajdonságok esetében nincs value vagy writable, helyette get és set függvények vannak.
Ez azt jelenti, hogy egy accessor leíró lehet:
-  get– egy argumentumok nélküli függvény, amely a tulajdonság olvasásakor működik,
-  set– egy argumentummal rendelkező függvény, amely a tulajdonság beállításakor hívódik,
-  enumerable– ugyanaz, mint az adattulajdonságoknál,
-  configurable– ugyanaz, mint az adattulajdonságoknál.
Egy fullName accessor defineProperty létrehozásához például átadhatunk egy get és set leírót:
let user = { name: "John", surname: "Smith"};Object.defineProperty(user, 'fullName', { get() { return `${this.name} ${this.surname}`; }, set(value) { = value.split(" "); }});alert(user.fullName); // John Smithfor(let key in user) alert(key); // name, surnameMegjegyezzük, hogy egy tulajdonság vagy accessor (get/set metódusokkal rendelkezik) vagy adattulajdonság (value-vel rendelkezik) lehet, de mindkettő nem.
Ha ugyanabban a leíróban megpróbáljuk megadni a get és a value tulajdonságot is, hiba fog jelentkezni:
// Error: Invalid property descriptor.Object.defineProperty({}, 'prop', { get() { return 1 }, value: 2});Smarter getterek/setterek
A getterek/setterek “valódi” tulajdonságértékek feletti burkolatként használhatók, hogy nagyobb kontrollt nyerjünk a velük végzett műveletek felett.
 Például, ha meg akarjuk tiltani a user túl rövid neveket, akkor lehet egy name setterünk, és az értéket egy külön _name tulajdonságban tarthatjuk:
let user = { get name() { return this._name; }, set name(value) { if (value.length < 4) { alert("Name is too short, need at least 4 characters"); return; } this._name = value; }};user.name = "Pete";alert(user.name); // Peteuser.name = ""; // Name is too short...A nevet tehát a _name tulajdonságban tároljuk, a hozzáférés pedig getter és setter segítségével történik.
Technikailag a külső kód a user._name használatával közvetlenül hozzáférhet a névhez. De van egy széles körben ismert konvenció, miszerint az "_" aláhúzással kezdődő tulajdonságok belsőek, és nem érinthetők az objektumon kívülről. 
A kompatibilitás érdekében
Az accessorok egyik nagyszerű haszna, hogy lehetővé teszik, hogy egy “rendes” adattulajdonság felett bármikor átvegyük az irányítást egy getterrel és egy setterrel való helyettesítéssel és a viselkedésének finomhangolásával.
Tegyük fel, hogy elkezdtük a felhasználói objektumok megvalósítását az name és age adattulajdonságok használatával:
function User(name, age) { this.name = name; this.age = age;}let john = new User("John", 25);alert( john.age ); // 25…De előbb-utóbb változhatnak a dolgok. Lehet, hogy a age helyett a birthday tárolása mellett döntünk, mert ez pontosabb és kényelmesebb:
function User(name, birthday) { this.name = name; this.birthday = birthday;}let john = new User("John", new Date(1992, 6, 1));Most mi legyen a régi kóddal, amely még mindig a age tulajdonságot használja?
 Megpróbálhatjuk megtalálni az összes ilyen helyet és kijavítani őket, de ez időt vesz igénybe és nehéz lehet, ha azt a kódot sok más ember használja. És különben is, a age egy szép dolog a user-ben, nem?
Maradjon meg.
 Egy getter hozzáadása a age-hez megoldja a problémát:
function User(name, birthday) { this.name = name; this.birthday = birthday; // age is calculated from the current date and birthday Object.defineProperty(this, "age", { get() { let todayYear = new Date().getFullYear(); return todayYear - this.birthday.getFullYear(); } });}let john = new User("John", new Date(1992, 6, 1));alert( john.birthday ); // birthday is availablealert( john.age ); // ...as well as the ageMost a régi kód is működik, és van egy szép további tulajdonságunk.