JavaScript Getters and Setters
Getters and setters are special methods that look like regular object properties but run code when you read or write them. A getter runs when you read a value. A setter runs when you assign a value. They let you add logic — like validation or formatting — without changing how the outside world interacts with the object.
The Analogy: A Smart Letter Box
A normal letter box: you drop a letter in, you take a letter out — no checks. A smart letter box with a getter and setter: when you put a letter in, it automatically checks the address and stamps it. When you take it out, it formats it nicely. The sender and receiver do not know the box does anything special.
Diagram: Get and Set Concept
Object Property (normal): person.name = "Raj" → just stores "Raj" person.name → just returns "Raj" Object Property (with getter/setter): person.name = "raj" → setter runs → stores "Raj" (capitalized) person.name → getter runs → returns "RAJ" (all caps)
Defining a Getter with get
Use the get keyword before a method name inside an object literal or class. Access it like a property — no parentheses needed.
let person = {
firstName: "asha",
lastName: "mehta",
get fullName() {
return this.firstName + " " + this.lastName;
}
};
console.log(person.fullName); // "asha mehta"
// Note: accessed like a property, not a method call
Defining a Setter with set
A setter receives the value being assigned and can validate or transform it.
let person = {
_age: 0,
get age() {
return this._age;
},
set age(value) {
if (value < 0 || value > 150) {
console.log("Invalid age!");
return;
}
this._age = value;
}
};
person.age = 25;
console.log(person.age); // 25
person.age = -5; // Invalid age!
console.log(person.age); // 25 (unchanged)
Diagram: Setter Validation Gate
person.age = -5
▼
[ Setter runs ]
│
Is -5 < 0? Yes
│
► Print "Invalid age!" and stop
│
_age stays unchanged = 25
person.age = 25
▼
[ Setter runs ]
│
Is 25 valid? Yes
│
► Store _age = 25
The Convention: Underscore Prefix
When you use a getter/setter pair for a property, the actual stored data usually lives in a private variable with an underscore prefix like _age or _name. This is a naming convention telling other developers: "do not access this directly — use the getter/setter instead."
Getters and Setters in Classes
The syntax is identical inside a class body.
class Circle {
constructor(radius) {
this._radius = radius;
}
get radius() {
return this._radius;
}
set radius(value) {
if (value <= 0) {
throw new Error("Radius must be positive");
}
this._radius = value;
}
get area() {
return Math.PI * this._radius ** 2;
}
get circumference() {
return 2 * Math.PI * this._radius;
}
}
let c = new Circle(5);
console.log(c.radius); // 5
console.log(c.area.toFixed(2)); // 78.54
console.log(c.circumference.toFixed(2)); // 31.42
c.radius = 10;
console.log(c.area.toFixed(2)); // 314.16
Diagram: Class with Getters
┌────────────────────────────────┐ │ Circle │ ├────────────────────────────────┤ │ _radius (stored value) │ │ │ │ get radius → read _radius │ │ set radius → validate, set │ │ get area → calculate area │ │ get circumference → calculate │ └────────────────────────────────┘ c.area → no data stored → calculated fresh from _radius each time
Computed Getter: No Data Storage Needed
Getters are perfect for derived values — values you can always compute from other stored data.
class Temperature {
constructor(celsius) {
this._celsius = celsius;
}
get celsius() { return this._celsius; }
get fahrenheit() { return this._celsius * 9/5 + 32; }
get kelvin() { return this._celsius + 273.15; }
set celsius(value) {
this._celsius = value;
}
}
let temp = new Temperature(100);
console.log(temp.celsius); // 100
console.log(temp.fahrenheit); // 212
console.log(temp.kelvin); // 373.15
temp.celsius = 0;
console.log(temp.fahrenheit); // 32
Object.defineProperty: The Low-Level Way
You can also add getters and setters to existing objects using Object.defineProperty.
let product = { _price: 0 };
Object.defineProperty(product, "price", {
get() {
return "₹" + this._price;
},
set(value) {
if (value < 0) throw new Error("Price cannot be negative");
this._price = value;
}
});
product.price = 500;
console.log(product.price); // ₹500
When to Use Getters and Setters
| Situation | Use Getter | Use Setter |
|---|---|---|
| Compute value from other properties | ✓ | |
| Validate input before storing | ✓ | |
| Format output (add currency symbol, etc.) | ✓ | |
| Log or track property changes | ✓ | |
| Make a read-only property | ✓ (no setter) |
Read-Only Property with Only a Getter
class User {
constructor(name) {
this._name = name;
this._createdAt = new Date().toISOString();
}
get createdAt() {
return this._createdAt;
}
}
let u = new User("Kiran");
console.log(u.createdAt); // ISO date string
u.createdAt = "2020-01-01"; // silently ignored (no setter)
console.log(u.createdAt); // still the original date
Summary
Getters and setters are special object methods that disguise themselves as properties. A getter runs logic when you read a property. A setter runs logic — like validation — when you write one. They keep the outside interface clean while letting the inside logic stay complex. Use getters for computed or formatted values, and setters to guard against invalid data. Classes and object literals both support the get and set keywords natively.
