Shyan Akarsha
Shyan Akarsha

Reputation: 11

What is the point of using getter and setter methods in Javascript

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

Answers (2)

derpirscher
derpirscher

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

T.J. Crowder
T.J. Crowder

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:

  • Validation: Ensuring that the value being set is a valid value for the property.
  • Side-effects: Taking action when the property is set (or read). For instance, you might log the fact the property was set/gotten, or in an MVVM/MVC setting, you might use the fact a property was changed to re-render a view.

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

Related Questions