Skip to main content

What is a property descriptor?

What a Property Descriptor is

A property descriptor is an internal object that describes the behavior of an object's property: whether it can be changed, enumerated, deleted, and whether it has a getter/setter.

Put simply:

It is the "metadata" about a property, not just its value but also the flags that define how it can be used.

Types of properties in JS

Properties come in two types:

  1. Data property → stores a specific value (value)
  2. Accessor property → defines get and/or set functions

The descriptor's structure

For a data property:

javascript
{ value: any, // the value writable: boolean, // whether value can change enumerable: boolean, // whether it shows up when iterating (for...in, Object.keys) configurable: boolean // whether it can be deleted or its descriptor changed }

For an accessor property:

javascript
{ get: function | undefined, // the getter set: function | undefined, // the setter enumerable: boolean, configurable: boolean }

Example: getting a descriptor

javascript
const user = { name: 'Tim' }; const descriptor = Object.getOwnPropertyDescriptor(user, 'name'); console.log(descriptor);

Prints:

javascript
{ value: 'Tim', writable: true, enumerable: true, configurable: true }

All of these flags default to true if the property is created the ordinary way.

Example: setting a property manually

javascript
const user = {}; Object.defineProperty(user, 'role', { value: 'admin', writable: false, // the value cannot be changed enumerable: false, // does not show up when iterating configurable: false // cannot be deleted or reconfigured }); console.log(user.role); // 'admin' user.role = 'user'; console.log(user.role); // 'admin' - the value did not change

Checking enumerability and configurability

javascript
const user = {}; Object.defineProperty(user, 'name', { value: 'Tim', enumerable: false, configurable: false }); console.log(Object.keys(user)); // [] - not enumerable delete user.name; // won't be deleted console.log(user.name); // 'Tim'

Example with a getter and setter

javascript
const person = {}; let _age = 25; Object.defineProperty(person, 'age', { get() { return _age; }, set(value) { if (value < 0) throw new Error('Age cannot be negative'); _age = value; }, enumerable: true, configurable: true }); console.log(person.age); // 25 person.age = 30; // calls the setter console.log(person.age); // 30

Defining properties in bulk

javascript
const user = {}; Object.defineProperties(user, { name: { value: 'Alex', writable: true, enumerable: true }, age: { value: 25, writable: false } });

Getting all of an object's descriptors

javascript
const obj = { a: 1, b: 2 }; console.log(Object.getOwnPropertyDescriptors(obj));

Result:

javascript
{ a: { value: 1, writable: true, enumerable: true, configurable: true }, b: { value: 2, writable: true, enumerable: true, configurable: true } }

Real-world use cases

  1. Creating "read-only" properties
javascript
Object.defineProperty(config, 'API_KEY', { value: '12345', writable: false });
  1. Hidden properties
javascript
Object.defineProperty(obj, '_id', { value: 42, enumerable: false });
  1. Implementing reactivity (for example, Vue.js uses get/set in descriptors to track changes)
  2. Simulating private fields (before # existed)
javascript
Object.defineProperty(obj, 'secret', { value: 'hidden', enumerable: false });

Summary

Descriptor propertyWhat it's for
valuethe value itself
writablewhether value can change
enumerablewhether it shows up when iterating
configurablewhether it can be deleted/redefined
getthe getter function
setthe setter function

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.