get name() {} and set name(value) {} in an object literal or class body define an accessor property: a property whose attributes are get, set, enumerable and configurable instead of value and writable.
- Read:
[[Get]]finds the accessor and calls the getter with the receiver (the object you read from) asthis. No getter meansundefined. - Write:
[[Set]]calls the setter with the new value. No setter means the write fails: silent in sloppy code, aTypeErrorin strict code ("Cannot set property x of # which has only a getter"). - No storage: the accessor holds functions, not data. The value lives elsewhere: another property (conventionally
_x), a closure, or a private field.
Because the receiver is this, an inherited accessor works on the child: child.balance = 10 runs the setter with this === child, so the data lands on child.
Where it shows up:
- Validation or normalisation on write.
- Derived, read-only values (
fullName,area). - Lazy computation.
- Built-ins:
Map.prototype.size,RegExp.prototype.flags, andObject.prototype.__proto__are getters.
Details:
- A literal's accessors are enumerable and configurable. Accessors in a
classbody live on the prototype and are non-enumerable, so they don't appear inObject.keysorJSON.stringifyof an instance. - Getter and setter functions get names like
get balanceandset balance. - A getter that reads its own property name (
get v() { return this.v; }) recurses until aRangeError. - Spread and
Object.assignread through the getter and store the plain value. They don't copy the accessor. Object.defineProperty(o, 'k', { get() {…}, set(v) {…} })creates the same thing programmatically.