The writable, enumerable and configurable flags
The writable, enumerable and configurable flags are three service parameters inside a property descriptor that control how an object's properties behave in JavaScript. They are invisible during everyday work with an object, yet they are what decides whether a property can be changed, deleted or enumerated.
Theory
TL;DR
| Flag | What it does | Default |
|---|---|---|
writable | Allows the property value to be changed | false (when the property is created through defineProperty) |
enumerable | Makes the property visible during enumeration (for...in, Object.keys) | false |
configurable | Allows the property to be deleted and its flags changed | false |
- A plain assignment
obj.key = valuecreates a property with all flags set totrue. - You read the flags with
Object.getOwnPropertyDescriptor(obj, key). - You can only set them through
Object.defineProperty(obj, key, descriptor).
Quick example
const user = {};
Object.defineProperty(user, 'name', {
value: 'Alice',
writable: false, // cannot be changed
enumerable: false, // does not appear in loops
configurable: false // cannot be deleted, flags cannot be changed
});
console.log(user.name); // "Alice"
user.name = 'Bob'; // does not change
delete user.name; // is not deleted
console.log(Object.keys(user)); // [] because the property is not enumeratedwritable: can the value be changed
const user = {};
Object.defineProperty(user, 'age', {
value: 25,
writable: false
});
user.age = 30; // will not work
console.log(user.age); // 25writable: trueallows the value to be changed;writable: falsemakes the property read only.
In sloppy mode a write to such a property is silently ignored, in strict mode it throws a TypeError.
enumerable: is the property shown during enumeration
const user = {};
Object.defineProperty(user, 'secret', {
value: '12345',
enumerable: false
});
console.log(user.secret); // readable directly
console.log(Object.keys(user)); // [] because the property is invisible
for (const key in user) console.log(key); // prints nothingenumerable: truemakes the property visible tofor...in,Object.keys(),JSON.stringify();enumerable: falsemakes it a hidden property.
A real world example: built-in methods (toString, valueOf) have enumerable: false so that they do not get in the way while iterating.
configurable: can it be deleted or its flags changed
const user = {};
Object.defineProperty(user, 'id', {
value: 10,
configurable: false
});
delete user.id; // will not be deleted
console.log(user.id); // 10
// Let us try to change writable:
Object.defineProperty(user, 'id', { writable: true });
// TypeError: Cannot redefine property: idconfigurable: trueallows the property to be deleted or its flags changed;configurable: falseforbids deletion and any change toenumerable,configurable, or movingwritablefromfalsetotrue.
The one thing you can still change on such a property is
writablefromtruetofalse, but not the other way round.
How to read and how to set the flags
Reading:
const obj = { name: 'Alice' };
const descriptor = Object.getOwnPropertyDescriptor(obj, 'name');
console.log(descriptor);Prints:
{
value: 'Alice',
writable: true,
enumerable: true,
configurable: true
}Setting:
Object.defineProperty(obj, 'prop', {
value: 42,
writable: false,
enumerable: true,
configurable: false
});Summary:
| Flag | Purpose | Example |
|---|---|---|
writable | Whether the property value can be changed | user.age = 30 |
enumerable | Whether the property is visible while iterating | Object.keys(user) |
configurable | Whether the property can be deleted or redefined | delete user.prop |
Common mistakes
- Forgetting that
definePropertysets every flag tofalse. A property created without an explicitenumerable: truevanishes fromObject.keys()and from theJSON.stringify()output. - Expecting an error when writing to a
writable: falseproperty. Without'use strict'the assignment silently fails and the bug is noticed late. - Confusing
writable: falsewith an immutable object. If the property holds an object, its fields can still be changed; deep freezing meansObject.freezeover the whole tree. - Counting on turning
configurableback totrue. It is a one way operation, so think first about which properties really need to be sealed. - Believing
enumerable: falsehides data. The property is still readable directly and still visible toObject.getOwnPropertyNames()andReflect.ownKeys(). - Using spread or
Object.assignto copy. They carry over only enumerable own properties and lose the flags; an exact copy needsObject.getOwnPropertyDescriptorsandObject.defineProperties.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.