Suggest an editImprove this articleRefine the answer for “The writable, enumerable and configurable flags”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**`writable`, `enumerable` and `configurable` are the three service flags of a property descriptor that control how an object's properties behave.** `writable` allows the value to be changed, `enumerable` makes the property visible during enumeration (`for...in`, `Object.keys`, `JSON.stringify`), and `configurable` allows the property to be deleted and the flags themselves to be changed. A plain assignment sets all three to `true`, while a property created through `Object.defineProperty` gets `false` by default. ```javascript const user = {}; Object.defineProperty(user, 'id', { value: 10, enumerable: true }); user.id = 42; // no change: writable is false console.log(Object.keys(user)); // ['id'] delete user.id; // not deleted: configurable is false ``` **Key point:** you read the flags with `Object.getOwnPropertyDescriptor(obj, key)`.Shown above the full answer for quick recall.Answer (EN)Image**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 = value` creates a property with all flags set to `true`. - You read the flags with `Object.getOwnPropertyDescriptor(obj, key)`. - You can only set them through `Object.defineProperty(obj, key, descriptor)`. ### Quick example ```javascript 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 enumerated ``` ### writable: can the value be changed ```javascript const user = {}; Object.defineProperty(user, 'age', { value: 25, writable: false }); user.age = 30; // will not work console.log(user.age); // 25 ``` - `writable: true` allows the value to be changed; - `writable: false` makes 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 ```javascript 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 nothing ``` - `enumerable: true` makes the property visible to `for...in`, `Object.keys()`, `JSON.stringify()`; - `enumerable: false` makes 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 ```javascript 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: id ``` - `configurable: true` allows the property to be deleted or its flags changed; - `configurable: false` forbids deletion and any change to `enumerable`, `configurable`, or moving `writable` from `false` to `true`. > The one thing you can still change on such a property is `writable` from `true` to `false`, but not the other way round. ### How to read and how to set the flags Reading: ```javascript const obj = { name: 'Alice' }; const descriptor = Object.getOwnPropertyDescriptor(obj, 'name'); console.log(descriptor); ``` Prints: ```javascript { value: 'Alice', writable: true, enumerable: true, configurable: true } ``` Setting: ```javascript 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 `defineProperty` sets every flag to `false`.** A property created without an explicit `enumerable: true` vanishes from `Object.keys()` and from the `JSON.stringify()` output. - **Expecting an error when writing to a `writable: false` property.** Without `'use strict'` the assignment silently fails and the bug is noticed late. - **Confusing `writable: false` with an immutable object.** If the property holds an object, its fields can still be changed; deep freezing means `Object.freeze` over the whole tree. - **Counting on turning `configurable` back to `true`.** It is a one way operation, so think first about which properties really need to be sealed. - **Believing `enumerable: false` hides data.** The property is still readable directly and still visible to `Object.getOwnPropertyNames()` and `Reflect.ownKeys()`. - **Using spread or `Object.assign` to copy.** They carry over only enumerable own properties and lose the flags; an exact copy needs `Object.getOwnPropertyDescriptors` and `Object.defineProperties`.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.