# Object accessors
Object accessors of accessor properties zijn gelijkaardig met een functie dat wordt uitgevoerd wanneer we een waarde toekennen (Eng. assign or setting a value) of een waarde opvragen (Eng. reading or getting a value). Ze zien er in code gelijkaardig uit met reguliere eigenschappen.
Getters en setters hebben een eenvoudige syntax gelijkaardig met eigenschappen en methoden, zorgen datakwaliteit en kunnen meerdere instructies achter de schermen uitvoeren.
In een object literal worden getters en setters gedefinieerd door respectievelijk door get en set:
let obj = {
get propName() {
// getter, the code executed on getting obj.propName
},
set propName(value) {
// setter, the code executed on setting obj.propName = value
}
};
2
3
4
5
6
7
8
9
De getter werkt door obj.propName aan te spreken, de setter door hieraan een waarde toe te kennen.
Hebben we bijvoorbeeld een user object met een firstname en lastname:
let user = {
firstname: "John",
lastname: "Doe"
};
2
3
4
We kunnen hieraan vervolgens een getter koppelen met de naam fullName dat als resultaat de volledige naam, bestaande uit de voornaam en familienaam, teruggeeft:
let user = {
firstname: 'John',
lastname: 'Doe',
get fullName() {
return `${this.firstname} ${this.lastname}`;
}
};
console.log(user.fullName); // John Doe
2
3
4
5
6
7
8
9
10
We roepen de getter (accessor property) aan zoals we een eigenschap aanroepen, dus niet als een functie. Proberen we nu een waarde toe te kennen aan de eigenschapsnaam (Eng. property name) dan zordt dit voor een fout Error (property has only a getter).
We kunnen dit oplossen door een setter voor de eigenschap fullName toe te voegen:
let user = {
firstname: 'John',
lastname: 'Doe',
get fullName() {
return `${this.firstname} ${this.lastname}`;
},
set fullName(value) {
[this.firstname, this.lastname] = value.split(' ');
}
};
console.log(user.fullName); // John Doe
user.fullName = 'Jane Doe';
console.log(user.fullName); // Jane Doe
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Het resultaat is een object accessor, accessor property of een virtual property fullName. We kunnen de setter in dit voorbeeld slimmer maken door extra logica hieraan toe te voegen. In dit geval houden we rekening met extra namen in de familienaam. De techniek bestaat erin om een string te splijten op basis van een spatie wat resulteert in een array van elementen, het eerste element komt in de variabele firstname terecht, de resterende elementen komen in de variabele lastname, wat een array is. Daarna maken we van deze array lastname een string om vervolgens de comma’s , te vervangen door een spatie.
let user = {
firstname: 'John',
lastname: 'Doe',
get fullName() {
return `${this.firstname} ${this.lastname}`;
},
set fullName(value) {
[this.firstname, ...this.lastname] = value.split(' ');
this.lastname = this.lastname.toString().replace(/,/g, ' ');
}
};
console.log(user.fullName); // John Doe
user.fullName = 'Philippe De Pauw - Waterschoot';
console.log(user.lastname); // De Pauw - Waterschoot
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
In het volgende voorbeeld maken we voor een gebruiker een username aan. Deze username moet wel minimaal 6 karakters bevatten.
let user = {
get username () {
return this._username;
},
set username(value) {
if (value.length < 6) {
throw new Error("Username is too short, need at least 6 characters");
return;
}
this._username = value;
}
};
try {
user.username = "drdyn";
} catch (error) {
console.log(error.toString()); // Error: Username is too short, need at least 6 characters
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Dit resulteert in een error. Deze error wordt opgevangen door een try...catch statement. Geven we een geldige naam in:
try {
user.username = "drdynscript";
console.log(`Your username is ${user.username}`); // Your username is drdynscript
} catch (error) {
console.log(error.toString());
}
2
3
4
5
6
Dan resulteert dit in het uitprinten van de username.
Externe code kan rechtstreeks de variabele _username manipuleren via user._username, maar dat is niet de bedoeling. Er is een conventie dat eigenschappen voorafgegaan met underscore _ intern zijn en bij voorkeur niet rechtstreeks aanfgesproken mag worden.
Getters en setters kunnen eveneens aangesproken worden binnenin een function constructor. Veronderstellen we het volgende voorbeeld waaring we de leeftijd berekenen van een persoon op basis van de geboortedatum. We kunnen een getter age aanmaken waarin deze logica vervat zitten.
Eerst definieren we een persoon User via een function constructor met twee parameters name en dayOfBirth. De waarden van deze parameters kennen we toe aan de corresponderende eigenschappen.
function User (name, dayOfBirth) {
this.name = name;
this.dayOfBirth = dayOfBirth;
}
let user = new User('Philippe', new Date(1984, 12, 12));
console.log(`Your birthday is ${user.dayOfBirth.toLocaleDateString()}`); // Your birthday is 1/12/1985
2
3
4
5
6
7
De bovenstaande code resulteert in een instantie van het User object of klasse. We geven bij het instantieren een string waarde en een date object mee. Deze worden toegekend als waarden van de corresponderende eigenschappen. We vragen in dit voorbeeld de geboortedatum op via de dayOfBirth eigenschap en de methode toLocaleDateString() (opens new window).
Om na de leeftijd te berekenen binnen deze User klasse, moeten we een nieuwe getter implementeren genaamd age. We gebruiken hiervoor de methode defineProperty() (opens new window).
function User (name, dayOfBirth) {
this.name = name;
this.dayOfBirth = dayOfBirth;
Object.defineProperty(this, 'age', {
get() {
let todayYear = new Date().getFullYear();
return todayYear - this.dayOfBirth.getFullYear();
}
});
}
let user = new User('Philippe', new Date(1984, 12, 12));
console.log(`Your age is ${user.age}`);
2
3
4
5
6
7
8
9
10
11
12
13
14