In a class, get and set define accessor properties: they look like fields from the outside, but run code.
class Rectangle {
constructor(width, height) {
this.width = width;
this.height = height;
}
get area() {
return this.width * this.height;
}
}
const rect = new Rectangle(4, 5);
console.log(rect.area); // → 20 (no parentheses)
rect.width = 10;
console.log(rect.area); // → 50 (always up to date)
area is computed each time it is read, so it can never be out of date, and you do not store it.
Setters validate
class Temperature {
#celsius = 0;
get celsius() {
return this.#celsius;
}
set celsius(value) {
if (typeof value !== "number" || Number.isNaN(value)) {
throw new TypeError("Temperature must be a number");
}
if (value < -273.15) {
throw new RangeError("Below absolute zero");
}
this.#celsius = value;
}
get fahrenheit() {
return this.#celsius * 9 / 5 + 32;
}
set fahrenheit(value) {
this.celsius = (value - 32) * 5 / 9;
}
}
const t = new Temperature();
t.celsius = 25;
console.log(t.fahrenheit); // → 77
t.fahrenheit = 212;
console.log(t.celsius); // → 100
try {
t.celsius = -500;
} catch (error) {
console.log(error.name); // → RangeError
}
Together with a private field, the setter guarantees that the stored value is always valid.
Read-only properties
A getter without a setter is read-only. Assigning to it is silently ignored in sloppy mode, and throws a TypeError in strict mode (inside modules, classes and "use strict" code).
class Circle {
constructor(radius) { this.radius = radius; }
get diameter() { return this.radius * 2; }
}
const c = new Circle(3);
function tryToChange() {
"use strict"; // code outside a class is only strict if you ask for it
c.diameter = 10;
}
try {
tryToChange();
} catch (error) {
console.log(error.name); // → TypeError
}
console.log(c.diameter); // → 6
Getters in the console
They are on the prototype, so they are not shown as own properties when you log the object, and JSON.stringify skips them.
Use them for
- Values derived from other fields (full name, total, area).
- Validation when a field is set.
- Keeping the public interface stable while the internal storage changes.
Do not hide slow or surprising work behind a getter. If it takes time, call it a method (calculateTotal()).
Static getters
static get version() { ... } also exists.