Reputation: 11
What is the point of using getter and setter methods. What exactly do they do and what are the benefits. I tried to make sense of them but I just don't get it and what is with the underscore that is used with the above methods. Can someone explain it to me. Thanks.
Upvotes: 0
Views: 112
Reputation: 17372
Depends on how you use them.
If the getter/setter just reads/writes the value of a public field (fields are public by default), they are probably not really needed. But when you are using private fields (ie protecting fields from direct manipulation from outside the class), you have to use getters and setters to change their value.
Furthermore, getters and setters may have some more logic (sanitation, validity checks, additional updates in the class, ...). You can even have properties, which are only calculated at runtime and are not backed up by a field at all.
Of course you can achieve the same with functions. But it seems more natural to access something that is a property of an object by "field syntax" than via a function.
See the following example: #firstname
and #lastname
are private fields of the person class, ie you can't access p.#firstname
. Thus, we need the FirstName
and LastName
properties to manipulate them. The getter just returns the value of the respective field, but the setter also checks, if the name is valid (although that specitic check may not make much sense, it's just an example). Furthermore, we have an additional getter for FullName
which returns a combination of first- and lastname.
class Person {
#firstname;
#lastname;
get FirstName() {
return this.#firstname;
}
set FirstName(fn) {
if (!fn || fn.length < 3)
throw "invalid first name"
this.#firstname = fn;
}
get LastName() {
return this.#lastname;
}
set LastName(ln) {
if (!ln || ln.length < 3)
throw "invalid last name"
this.#lastname = ln;
}
get FullName() {
return `${this.#firstname} ${this.#lastname}`;
}
constructor(fn, ln) {
this.#firstname = fn;
this.#lastname = ln;
}
}
let p = new Person("John", "Doe");
//if you uncomment this, you will get a syntax error
//p.#firstname = "Jane";
console.log(p.FirstName);
console.log(p.LastName);
p.FirstName = "Jane";
console.log(p.FullName);
try {
p.LastName = "D."
} catch (e) {
console.log(e);
}
Upvotes: 1
Reputation: 1074028
Accessor properties provide a way to call a function when a property is read (get
) or written to (set
), even though the code doing that is using property access or assignment syntax. Here's an example of a getter:
const example = {
get random() {
return Math.random();
}
};
const r = example.random;
console.log(r);
Notice that there is no ()
on random
in that example, it looks like a straight data property access. But in fact it's a hidden function call.
Setters work the same way, but when you assign to the property rather than when you read it:
const example = {
set something(value) {
console.log(`setter called with ${value}`);
}
};
example.something = 42;
Because they're function calls, no value is stored unless the function(s) store it.
There are a few reasons you might want to have accessor properties rather than standard data properties. For instance:
Here's an example of a property you can only set to a number:
class Example {
#storedValue = 0;
set value(value) {
const type = typeof value;
if (type !== "number") {
throw new Error(`Value must be of type number, not ${type}`);
}
this.#storedValue = value;
}
get value() {
return this.#storedValue;
}
}
const e = new Example();
e.value = 42;
console.log(e.value); // 42
e.value = "something"; // Throws error
That uses the fairly-new private fields feature to store the value where it can't be accessed from outside the class, so you have to go through the accessor property to get to it. That lets the class validate the values you assign.
Upvotes: 1