Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Getters and setters

Sometimes a property should not just store a value but do something: compute a result on the fly or check what is being written into it. Getters and setters exist for this — methods that look like ordinary properties from the outside.

A getter

The get keyword before a method turns it into a getter. You access it like a property, without parentheses, and it returns the method's result:

class User {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }
 
  get fullName() {
    return `${this.firstName} ${this.lastName}`;
  }
}
 
const user = new User('Anna', 'Smith');
 
console.log(user.fullName); // Anna Smith

A computed value is always up to date

A getter computes the value on every access, so it never goes stale when the source data changes:

class Cart {
  items = [];
 
  get total() {
    return this.items.reduce((sum, item) => sum + item.price, 0);
  }
}
 
const cart = new Cart();
cart.items.push({ title: 'Tea', price: 5 });
cart.items.push({ title: 'Coffee', price: 12 });
 
console.log(cart.total); // 17

There is no need to keep the total in a separate property and remember to recalculate it.

A setter

The set keyword declares a setter — a method that runs when the property is written to. The written value arrives in its parameter:

class User {
  set name(value) {
    this.firstName = value.trim();
  }
}
 
const user = new User();
user.name = '  Oleg  ';
 
console.log(user.firstName); // Oleg

Validating a value

The main benefit of a setter is validation. Together with a private field it will not let an invalid value into the object:

class Product {
  #price = 0;
 
  get price() {
    return this.#price;
  }
 
  set price(value) {
    if (value < 0) {
      throw new Error('Price cannot be negative');
    }
    this.#price = value;
  }
}
 
const product = new Product();
product.price = 25;
 
console.log(product.price); // 25

Writing product.price = -5 would throw an error, and the wrong price would never reach the object.

A read-only property

If you declare a getter without a setter, the property can only be read. Writing to it does not work: in an ordinary script it is silently ignored, and in modules and strict mode it throws a TypeError:

class Circle {
  constructor(radius) {
    this.radius = radius;
  }
 
  get diameter() {
    return this.radius * 2;
  }
}
 
const circle = new Circle(5);
circle.diameter = 100;
 
console.log(circle.diameter); // 10

Common mistake

Inside a setter you must not write the value to a property with the same name. Such a write calls the setter again, which calls itself again, and the program crashes with a stack overflow error:

class User {
  set name(value) {
    this.name = value; // the setter calls itself forever
  }
}

Store the value in a field with a different name — usually a private one: this.#name = value.

Thanks for reading!

Donate to the site — we work hard for you.