Step 1 of 7 · Reading · ~3 min
Learn
Collections and Property Descriptors
Property Descriptors and Getters/Setters
Every property of an object carries a small record of settings: whether it can be changed, listed or deleted. By default you never see it, but Object.freeze, getters, setters and class accessors are all built on it. By the end of this lesson you can read and set those settings, write computed properties, and choose between freeze, seal and #private fields.
The descriptor
A data property has a value plus three flags:
writable: whether the value can be reassigned.enumerable: whether the property appears inObject.keys,for...in, spread ({...obj}) andJSON.stringify.configurable: whether the property can be deleted or its flags changed.
Properties made by assignment or in an object literal have all three set to true.
Object.defineProperty
Object.defineProperty(obj, name, descriptor) adds or changes a property with exactly the flags you give. Flags you leave out default to false, the opposite of normal assignment:
Without "use strict" those last two lines fail silently, which is worse: nothing changes and nothing tells you. Classes and ES modules are always strict.
Accessor properties: getters and setters
Instead of a stored value, a property can have a get function and/or a set function. Reading runs the getter; assigning runs the setter. From outside it looks like a normal property.
The same is available in literals (get gross() {...}) and classes. A setter is the natural place to validate:
A #name field is private by syntax: code outside the class body cannot even mention it, unlike an _underscore convention that anyone can ignore.
freeze, seal, preventExtensions
| Call | Add properties | Delete | Change values |
|---|---|---|---|
Object.preventExtensions(o) | no | yes | yes |
Object.seal(o) | no | no | yes |
Object.freeze(o) | no | no | no |
Object.isFrozen(o), isSealed and isExtensible report the state. All three are shallow: Object.freeze({ nested: { n: 1 } }) still lets you set nested.n. And they cannot be undone. A spread copy of a frozen object is a normal, unfrozen object, because flags are not copied.
Common mistakes
- Expecting
definePropertyto behave like assignment. Missing flags arefalse. - Assuming a frozen object is deeply immutable.
- Forgetting that failed writes are silent outside strict mode.
- Giving an accessor both a
valueand aget: it is one kind or the other. - Looking for a class's getters in
JSON.stringifyorObject.keys. They live on the prototype and are skipped.
Your exercise
Combine all of it in one function: copy some data, add a hidden read-only property and a computed one, then lock the result. The starter then probes every flag from the outside.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…