Using getters and setters in JavaScript classes

Updated: March 16, 2023 By: Khue Post a comment

Introduction

In JavaScript, getters and setters are special methods that allow a class to define how to access and modify its properties. They have many use cases, such as:

  • Creating a read-only property that cannot be changed by external code
  • Creating a property that has a default value based on another property
  • Creating a property that triggers some side effects when it is changed (see the last example)

This concise, straightforward article will show you how to define getters and setters in JavaScript classes. You will also learn the way getters and setters work with inheritance and super calls. And indispensable, of course, you will see code in several highly practical examples.

Define Getters & Setters

The get and set keywords are used to define getter and setter methods in JavaScript classes.

Example

The code:

class Website {
  constructor(name, age, description) {
    this.name = name;
    this.age = age;
    this.description = description;
  }

  // getter method
  get description() {
    return this._description;
  }

  // setter method
  set description(newDescription) {
    this._description = newDescription.trim();
  }
}

let website = new Website(
  'Sling Academy',
  '10',
  'A website about programming, math, and data science.'
);
console.log(website.description); 
website.description = 'The best place to learn to code.'; 
console.log(website.description); 

Output:

A website about programming, math, and data science.
script.js:26 The best place to learn to code.

In this example, the description getter method returns the value of the _description property of the website object. The description setter method changes the value of the _description property to a new value and removes any leading or trailing whitespace. Note that when using getter and setter methods, you do not need to use parentheses to invoke them.

What about the underscore?

In the previous example, the setter method trims the whitespace from the new description value before assigning it to the _description property.

The underscore is used to indicate that the property is private, meaning that it should not be accessed or modified directly by other codes. This is a common convention in JavaScript, but it is not enforced by the language. Using getter and setter methods allows you to control how the property is accessed and modified, and to perform any validation or computation before returning or assigning the value.

See also: Private, Protected, and Public Class Members in JavaScript

Using Getters and Setters with Inheritance and Super Calls

What are the points?

Some key concepts about JavaScript class inheritance and how to use getters and setters with it:

  • Class inheritance is a way for one class to extend another class. For example, you can create a class named ChildClass that inherits all the methods from another class named ParentClass.
  • To create a class inheritance, use the extends keyword.
  • The super() method refers to the parent class. By calling the super() method in the constructor method, you call the parent’s constructor method and get access to the parent’s properties and methods.
  • You can also use super to access the parent’s getters and setters.

Now, it’s time to go ahead and practice.

Example

Before we look at the code example, let me explain what we are going to do. We are going to define 2 classes: Project and Website. The Project class will represent a general project with a name and a deadline. The Website class will represent a specific type of project that also has a url and a launch method. We want the Website class to inherit from the Project class so that it can use its properties and methods.

The complete code (it’s quite long, but the majority are comments and explanations):

// Define a parent class named Project
class Project {
  // Define a constructor that takes a name and a deadline parameter
  constructor(name, deadline) {
    this._name = name; // Assign the name to a private property
    this._deadline = deadline; // Assign the deadline to a private property
  }

  // Define a getter for the name property
  get name() {
    return this._name;
  }

  // Define a setter for the name property
  set name(newName) {
    this._name = newName;
  }

  // Define a getter for the deadline property
  get deadline() {
    return this._deadline;
  }

  // Define a setter for the deadline property
  set deadline(newDeadline) {
    this._deadline = newDeadline;
  }

  // Define a method that returns the status of the project
  getStatus() {
    let today = new Date(); // Get today's date
    let diff = Math.ceil((this._deadline - today) / (1000 * 60 * 60 * 24)); // Calculate the difference in days between today and deadline

    if (diff > 0) {
      // If there is still time left
      return `The project ${this._name} has ${diff} days left until the deadline.`;
    } else if (diff == 0) {
      // If today is the deadline
      return `The project ${this._name} is due today.`;
    } else {
      // If the deadline has passed
      return `The project ${this._name} is overdue by ${-diff} days.`;
    }
  }
}

// Define a child class named Website that inherits from Project
class Website extends Project {
  constructor(name, deadline, url) {
    super(name, deadline); // Call the parent's constructor with the name and deadline parameters
    this._url = url; // Assign the url to a private property
  }

  get url() {
    return this._url;
  }

  set url(newUrl) {
    this._url = newUrl;
  }

  launch() {
    return `The website ${this.name} has been launched at ${this.url}.`;
  }
}

// Create an instance of Website
let portfolio = new Website(
  'Sling Academy',
  new Date(2023, 2, 31),
  'www.slingacademy.com'
);

// Access and modify the properties using getters and setters
console.log(portfolio.name);
console.log(portfolio.deadline);
console.log(portfolio.url);

// Change the name using setter
portfolio.name = 'Sling Academy 4.0';
// Change the deadline using setter
portfolio.deadline = new Date(2025, 3, 15);

console.log(portfolio.getStatus());
console.log(portfolio.launch());

Output:

Sling Academy
Fri Mar 31 2023 00:00:00 GMT+0000 (UTC)
www.slingacademy.com
The project Sling Academy 4.0 has 761 days left until the deadline.
The website Sling Academy 4.0 has been launched at www.slingacademy.com.

Another Example (Advanced)

Getters and setters are methods that allow you to control how a property of an object is accessed or modified. They can be useful for creating a property that triggers some side effects when it is changed, such as validating the input, updating other properties, or firing events.

Suppose you have a class named Person that has a name and an age property. You want to make sure that the name is always capitalized and that the age is always positive. You can use getters and setters to achieve this:

class Person {
  constructor(name, age) {
    this._name = name; // Use an underscore to indicate a private property
    this._age = age;
  }

  // Define a getter for the name property
  get name() {
    return this._name.toUpperCase(); // Return the name in uppercase
  }

  // Define a setter for the name property
  set name(newName) {
    if (typeof newName === 'string') {
      // Check if the input is a string
      this._name = newName; // Update the private property
    } else {
      console.log('Invalid name.'); // Reject invalid input
    }
  }

  // Define a getter for the age property
  get age() {
    return this._age; // Return the age as it is
  }

  // Define a setter for the age property
  set age(newAge) {
    if (typeof newAge === 'number' && newAge > 0) {
      // Check if the input is a positive number
      this._age = newAge; // Update the private property
    } else {
      console.log('Invalid age.'); // Reject invalid input
    }
  }
}

// Create an instance of Person
let lonewolf = new Person('Lonewolf', 35);

// Access and modify the properties using getters and setters
console.log(lonewolf.name); // LONEWOLF
console.log(lonewolf.age); // 35

lonewolf.name = 'Big Boss'; // Change the name using setter
lonewolf.age = -10; // Try to change the age using setter (invalid age)

console.log(lonewolf.name); // BIG BOSS
console.log(lonewolf.age); // 35

As you can see, getters and setters allow you to manipulate how a property is accessed or modified, and to trigger some side effects when it is changed.

Conclusion

You’ve learned how to use getters and setters in JavaScript classes through some practical examples in this article. They can help you write better code that is more robust, efficient, and flexible.

If you find errors or anachronisms in the code examples, please let us know by leaving comments. We will review and update them as soon as possible.