Skip to content
Property Descriptors and Getters/Setters
step 1/7

Reading — step 1 of 7

Learn

~3 min readCollections and Property Descriptors

Every property in a JavaScript object has metadata — its descriptor. You usually never see them, but tools like Object.freeze, Object.defineProperty, and class accessor syntax all manipulate them.

What's a descriptor?

javascript

Four flags every plain property has:

  • value — the actual value
  • writable — can it be reassigned with obj.x = ...?
  • enumerable — does it show up in Object.keys, for...in, JSON.stringify?
  • configurable — can the descriptor itself be changed (or property deleted)?

Assigning normally (obj.x = 1) creates a property with all four set to true.

Object.defineProperty — fine control

javascript

Used for hidden internal properties on objects, locking down library APIs, defining constants.

Getters and setters (accessor properties)

Instead of a stored value, define functions that run when the property is accessed:

javascript

In classes:

javascript

Getters/setters look like properties from the outside but compute on access.

Object.freeze — make it immutable

javascript

Freeze sets writable=false and configurable=false on every property AND prevents adding new properties. SHALLOW — nested objects are still mutable.

For deep immutability:

javascript

Object.seal — between freeze and normal

  • Object.preventExtensions(obj) — can't ADD properties; existing still mutable
  • Object.seal(obj) — also can't DELETE; existing still writable
  • Object.freeze(obj) — also can't WRITE

Private fields (ES2022)

For genuine privacy in classes, use #-prefixed fields:

javascript

Private fields are syntax-level private — not just convention. Reflection won't find them.

Common mistakes

  • Confusing freeze with deep freeze — Object.freeze is shallow.
  • Using underscore prefix as 'privacy'_x is a convention, anyone can read it. Use # for real privacy.
  • Forgetting strict-mode behavior — assignments to frozen properties silently fail in sloppy mode but throw in strict.
  • Creating non-enumerable properties accidentally — using Object.defineProperty without specifying enumerable defaults all flags to false.
  • Accessor properties in JSON — getters run during JSON.stringify (their return value is serialized) but don't round-trip; the parse side won't recreate the getter.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…