Lesson 57: Mastering JavaScript Property getters and setters with challenges!

β What Are Property Accessors?
Accessors are virtual properties in JavaScript that look like normal properties, but are backed by functions that run when you get or set them.
They let you:
Add computed logic when reading a property.
Control and validate how a property is set.
Seamlessly migrate data formats (e.g., replace
.age
with.birthday
without breaking existing code).
β¨ Syntax in Object Literals
let user = {
firstName: "John",
lastName: "Smith",
get fullName() {
return `${this.firstName} ${this.lastName}`;
},
set fullName(value) {
[this.firstName, this.lastName] = value.split(" ");
}
};
console.log(user.fullName); // John Smith
user.fullName = "Alice Cooper";
console.log(user.firstName); // Alice
π§ Syntax via Object.defineProperty
let user = { firstName: "John", lastName: "Smith" };
Object.defineProperty(user, 'fullName', {
get() {
return `${this.firstName} ${this.lastName}`;
},
set(value) {
[this.firstName, this.lastName] = value.split(" ");
},
enumerable: true,
configurable: true
});
π Flowchart: Accessor Execution
user.fullName ββββββ> getter() executed βββββ> value returned
β
user.fullName = "x" ββββββ> setter(value) executed β> side-effects or update
πΉ 2. Fill Any Gaps
π¨ What Most People Miss
1. Accessors are not compatible with value
/writable
You cannot mix get/set
with value
or writable
in the same descriptor.
Object.defineProperty(obj, "x", {
get() { return 42 },
value: 10 // β Error!
});
2. Only configurable descriptors can be updated
Trying to change an accessor on a non-configurable property throws an error.
3. Accessors and Prototypes
Inherited accessor properties (from prototype
) behave just like data properties. The this
inside the getter/setter refers to the receiver, not the prototype.
let proto = {
get name() {
return this._name?.toUpperCase();
},
set name(value) {
this._name = value;
}
};
let user = Object.create(proto);
user.name = "john";
console.log(user.name); // JOHN
4. Descriptor differences
Descriptor Type | Has value | Has get/set | writable valid? |
Data Property | β | β | β |
Accessor | β | β | β |
β οΈ Pitfalls
Circular setter logic (setter calls itself)
Forgetting
enumerable: true
when usingdefineProperty
Using accessors for performance-critical code (introduces function overhead)
πΉ 3. Challenge Me Deeply
π’ Basic
Create a user object where
email
is stored in_email
, but you exposeemail
through a getter/setter that ensures it's always lowercase.Write a class
Product
with a computedpriceWithTax
getter (base price + 18% GST).Create a
Counter
object with acount
data property, and adouble
getter that returns twice the current count.
π‘ Intermediate
Use
Object.defineProperty
to create a non-enumerablesecret
getter/setter on an object.Implement an object where
fullName
getter returnsfirstName
+lastName
, and setter splits and sets them.Make a
Rectangle
class wherearea
is a getter, andresize(newArea)
method uses setter logic internally.
π΄ Advanced
Create a proxy object that intercepts setting
salary
and applies a 10% deduction tax inside a setter.Implement a class where
age
is virtual (via getter) based on a private_dob
Date.Write a class with a
password
setter that logs a hash to console but doesn't store it.Use
Object.defineProperty
to create a lazy getter (e.g.,user.profile
) that fetches data only once, then caches it.
π― Aha! Brain-Twister
- What happens if a getter tries to access itself? Design an object where
getter
callsthis.getter
inside β predict the output.
πΉ 4. Interview-Ready Questions
β Conceptual
What are accessor properties and how are they different from data properties?
Can a property have both a getter and a value? Why not?
π Scenario-Based
If
obj.name
is defined with only a getter and someone tries to assign to it, what happens?You want to prevent direct mutation of an internal
_balance
value, but allow reading and restricted updates β how would you architect that?
π Debugging
A developer reports
.name
isnβt updating in the UI. You find itβs an accessor. What might be the issue?The getter on a prototype object is returning undefined β what are the likely causes?
π¨ Best Practices & Red Flags
β Good:
Use
_underscore
naming convention for internal values behind getters.Keep logic inside accessors short and deterministic.
Use for backward compatibility or derived properties.
β Bad:
Doing async operations inside getters.
Mutating state inside getters.
Making getters non-enumerable without intention.
πΉ 5. Real-World Usage
π§ In Frameworks
Vue.js (before Composition API): reactive state uses
Object.defineProperty
for getters/setters.MobX: uses accessors to track dependencies and mutations.
Backbone.js: relies heavily on getter-style accessors for models.
ORMs: Accessors often wrap DB properties for formatting, validation, and transformation.
π Production Use Cases
Format
price
to include currency symbol dynamically.Auto-calculate
isExpired
from atimestamp
field.Prevent invalid assignments with validation logic in setters.
πΉ 6. Remember Like a Pro
π§ Mnemonic: "G-SET" β like get
and set
G β Getter runs when you Get
S β Setter runs when you Set
E β Enumerable is optional
T β Two separate functions, not mixed with value
πΊοΈ Visual Cheatsheet
βββββββββββββ Accessor ββββββββββββββ
β getter() β on get β
β setter(value) β on assignment β
ββββββββββββββββββββββββββββββββββββ
βββββββββββββ Data βββββββββββββββ
β value: 42 β
β writable: true β
βββββββββββββββββββββββββββββββββ
πΉ 7. Apply It in a Fun Way
π§© Mini Project: Smart User Profile
π§ Build a User
class with:
_dob
(private birth date)age
β getter that calculates agefullName
β getter/setter that syncsfirstName
andlastName
email
β setter that ensures lowercaseMake
profileSummary
β computed string with all info
π¦ Steps
Create
User
class with constructor forname
,dob
,email
Add a
get age()
that calculates fromdob
Add
get/set fullName
for syncing name partsAdd email validation/lowercasing in
set email
Add
get profileSummary()
to print formatted data
π‘ Extend it by:
Adding a
freeze()
method to lock the user object (Object.freeze
)Emit an event when
email
is changed
β Bonus Insights
ποΈ Open Source Projects
Vue 2 reactivity system
MobX dynamic observable properties
AngularJS 1.x dirty checking with
Object.defineProperty
𧨠Common Mistakes
Forgetting to define both getter and setter for computed properties.
Doing expensive or asynchronous logic inside a getter.
Confusing data and accessor descriptors.
π Performance Tips
Use getters for derived data, not for logic-heavy computation.
Avoid changing accessors frequently in performance-critical paths.
π‘οΈ Modern Alternatives
For reactivity, prefer Proxy in modern frameworks (Vue 3, Svelte).
Use #private fields in classes to encapsulate internal values instead of
_underscoring
.
Subscribe to my newsletter
Read articles from manoj ymk directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
