Descriptors control writability, enumerability and reconfiguration. Data descriptors define value and writable; accessor descriptors define get and set.
Step-by-step walkthrough
Step 1: Choose a property contract
Decide whether callers may write, enumerate or redefine the property. A data property stores a value; an accessor computes through get and set. These are different descriptor shapes and should not be mixed in one definition.
Step 2: Specify flags explicitly
DefineProperty defaults omitted flags to false for a newly created property. Ordinary assignment creates a different everyday property shape. Candidates should explain why a property may appear in direct access while being missing from Object.keys.
Step 3: Account for access effects
A getter can execute code on every read and can fail or change other state. Copying values and copying descriptors therefore have different meanings. Diagnostic or serialization code should not assume every property read is passive.
Worked scenario
A property defined without enumerable does not appear in Object.keys. Omitted descriptor flags default to false for a new property.
const user = {};
Object.defineProperty(user, 'id', {
value: 'u1', writable: false,
enumerable: true, configurable: false
});
console.log(Object.keys(user)); // ['id']
console.log(Object.getOwnPropertyDescriptor(user, 'id').writable); // falseWalk through the example
The identifier participates in enumeration but cannot be assigned a replacement through this descriptor. In strict mode a prohibited write can throw; code should not depend on silent failure. The flags protect this property’s binding, not every nested value if the stored value were an object.
Common mistake
A getter can execute code; reading a property is not always passive.
Verify the behavior
Check direct reading, enumeration, a strict-mode attempted write and attempted redefinition. For accessor properties, count getter calls during copying or logging and verify any side effects are intentional. Include a descriptor omitted-flags case to make its defaults visible.
Interview exercise
Why is an identifier absent from enumeration?
Answer and reasoning
Inspect its descriptor. Set enumerable explicitly if iteration should expose it; define writable and configurable according to ownership.
Follow-up discussion
Does a getter make data read-only? Omitting a setter prevents ordinary assignment to that accessor, but the getter’s returned object may still be mutable. Should private data be hidden through enumerable false? It reduces enumeration, not authorized access or confidentiality.
Continue learning
Compare the scenario with the JavaScript interview questions and test your understanding with the JavaScript MCQs. For terminology and implementation details, consult the reference material.