Skip to Content
Course content

73: Getters and Setters in Classes

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I see this all the time when I'm reviewing code from developers moving into JavaScript: they treat getters and setters as just another way to name their methods. They'll create a class and write methods like getName() and setName(value), thinking they are following a "best practice" from other languages like Java. While that works, it's not actually using JavaScript's built-in getter and setter functionality. It's just writing regular methods.

Thinking getters and setters are just methods with "get" in the name

If you're manually calling a function to get a value, you aren't using a JavaScript getter. Look at this snippet. This is the "manual" way that many people default to:

class SmartLight {
  constructor(brightness) {
    this._brightness = brightness;
  }

  // This is just a method, NOT a JS getter
  getBrightness() {
    return `${this._brightness}%`;
  }

  // This is just a method, NOT a JS setter
  setBrightness(value) {
    if (value < 0 || value > 100) {
      console.error("Brightness must be between 0 and 100");
      return;
    }
    this._brightness = value;
  }
}

const light = new SmartLight(50);
console.log(light.getBrightness()); // We have to call it as a function
light.setBrightness(75);            // We have to call it as a function

This approach is clunky. From the perspective of the person using your class, they have to remember that brightness isn't a property—it's a set of functions. It breaks the intuition of how objects usually work in JavaScript.

Using the get and set keywords to treat methods like properties

JavaScript allows us to define "accessor properties." By using the get and set keywords, we can execute logic behind the scenes while the outside world thinks they are just accessing a simple variable. This is the real power of getters and setters.

class SmartLight {
  constructor(brightness) {
    this._brightness = brightness;
  }

  // Now it's a getter!
  get brightness() {
    return `${this._brightness}%`;
  }

  // Now it's a setter!
  set brightness(value) {
    if (value < 0 || value > 100) {
      console.error("Brightness must be between 0 and 100");
    } else {
      this._brightness = value;
    }
  }
}

const light = new SmartLight(50);

// Notice: No parentheses! It looks like a property.
console.log(light.brightness); // "50%"

// Notice: We use the assignment operator (=), not a function call.
light.brightness = 75; 
console.log(light.brightness); // "75%"

light.brightness = 150; // "Brightness must be between 0 and 100"

Do you see the difference? The API is much cleaner. The user of the SmartLight class doesn't need to care that there is validation logic happening under the hood; they just assign a value to brightness.

Now, here is a critical warning that will save you hours of debugging: Never name the internal property the same as the getter/setter.

In my example, I used this._brightness (with an underscore) inside the setter, while the setter itself is named brightness. If I had written this.brightness = value inside the setter, the setter would call itself, which would call itself, and so on, until you hit a "Maximum call stack size exceeded" error. The underscore is a convention in the JS community to signal, "Hey, this is a private-ish variable, don't touch it directly from outside the class."

  • Use get when you want to format a value or calculate a property on the fly.
  • Use set when you need to validate data before it's saved to the object.
  • Always use a different internal name (like _variable) to avoid infinite recursion.



📋 Practical Task

Build a Temperature Converter Class

Create a class called Thermostat. The class should store the temperature internally in Celsius, but provide a way to interact with it in Fahrenheit.

  • The constructor should accept an initial temperature in Celsius and store it in a property called _celsius.
  • Create a getter called fahrenheit that converts the internal Celsius value to Fahrenheit (Formula: (Celsius * 9/5) + 32) and returns it.
  • Create a setter called fahrenheit that takes a Fahrenheit value, converts it back to Celsius (Formula: (Fahrenheit - 32) * 5/9), and updates the internal _celsius property.
  • Add a safety check in the setter: if the Fahrenheit value provided is below -459.67 (absolute zero), log an error message and do not update the temperature.

Test your code: Instantiate the class with 25 degrees Celsius. Log the fahrenheit property to ensure it's 77. Then, set fahrenheit to 100 and log the internal _celsius to see if it updated correctly.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.