Property Flags & Descriptors

Medium100% Free~25 mins#objects#property-descriptors#define-property#enumerable#writable#configurable#getters-setters
Key Learning Objectives
✓

Understand the 3 core property flags: writable (mutability), enumerable (iteration visibility), and configurable (deletion & descriptor modification).

✓

Master the critical default behavior: Object.defineProperty() defaults omitted flags to false, while normal assignment defaults them to true.

✓

Distinguish between Data Descriptors (value, writable) and Accessor Descriptors (get, set).

✓

Identify silent failures in non-strict mode versus TypeErrors thrown in strict mode for read-only or non-configurable properties.

✓

Know how Object.keys(), Object.getOwnPropertyNames(), and Reflect.ownKeys() handle property enumeration.

The Interview Problem

What is logged to the console when the following code executes, and how do Object.defineProperty descriptor defaults affect enumeration, mutation, and deletion?

1const obj = {};
2
3Object.defineProperty(obj, 'id', {
4 value: 101,
5 // writable, enumerable, configurable omitted
6});
7
8obj.title = 'Widget';
9
10const keys = Object.keys(obj);
11
12obj.id = 999;
13
14const deleteId = delete obj.id;
15
16const ownNames = Object.getOwnPropertyNames(obj);
17
18console.log(keys.join(','), obj.id, deleteId, ownNames.join(','));
Predict Console Output
Interactive Challenge

Select the option that matches what standard ECMAScript prints to the console:

title 101 false id,title

id,title 999 true id,title

title 999 false title

title 101 true id,title

V8 Engine Execution Trace
Step 1 of 7 (Line 3)

Object.defineProperty defines 'id'. Because flags are omitted, the V8 engine defaults writable: false, enumerable: false, configurable: false.

Call Stack (Top = Active)
Global Execution Context
Object.defineProperty()
Lexical Scope / Bindings
obj.id:{ value: 101, writable: false, enumerable: false, configurable: false }
Console Stream
> [empty]

Deep Technical Breakdown

Anatomy of JavaScript Property Descriptors

Every object property in JavaScript possesses an underlying Property Descriptor managed by the engine. Descriptors fall into two mutually exclusive categories:

  1. Data Descriptors: Describe properties that hold a direct value.
    • value: The stored JavaScript value (default undefined).
    • writable: If true, the value can be changed via assignment. If false, reassignment fails (silently in non-strict mode, throws TypeError in strict mode).
  2. Accessor Descriptors: Describe properties with getter/setter functions.
    • get: A function called when reading the property.
    • set: A function called when writing to the property.
      (Note: A descriptor cannot have both value/writable and get/set simultaneously; doing so throws a TypeError.)
  3. Shared Descriptor Flags:
    • enumerable: If true, the property appears in for...in loops and Object.keys(). If false, it is omitted.
    • configurable: If true, the property can be deleted via delete, and its descriptor attributes can be modified. If false, delete fails and changing descriptor flags throws a TypeError.

The Great Default Discrepancy

Creation Methodwritableenumerableconfigurable
Assignment (obj.prop = 'val')truetruetrue
Object.defineProperty (omitted flags)falsefalsefalse

Inspection Methods

javascript
const descriptor = Object.getOwnPropertyDescriptor(obj, 'prop');
const allDescriptors = Object.getOwnPropertyDescriptors(obj);

Introspection Differences

  • Object.keys(obj): Own enumerable string keys only.
  • Object.getOwnPropertyNames(obj): All own string keys (both enumerable and non-enumerable).
  • Object.getOwnPropertySymbols(obj): All own symbol keys.
  • Reflect.ownKeys(obj): All own keys (both string and symbol, enumerable and non-enumerable).

Strict Mode vs Non-Strict Mode

In non-strict mode:

  • Writing to a non-writable property fails silently.
  • Deleting a non-configurable property returns false.

In strict mode ('use strict'):

  • Writing to a non-writable property throws TypeError: Cannot assign to read only property.
  • Deleting a non-configurable property throws TypeError: Cannot delete property.
Common Traps & Mistakes

Assuming Object.defineProperty defaults omitted descriptor flags to true. They always default to false.

Mixing data and accessor flags (e.g. providing both value and get), which throws an immediate TypeError.

Thinking Object.freeze() creates a deep freeze. Object.freeze() only sets configurable: false and writable: false on own properties shallowly.

Forgetting that strict mode turns silent property descriptor write failures into fatal runtime exceptions.

FAANG Follow-Up Probes
Probe #1

How does Object.seal() differ from Object.freeze() in terms of property descriptors?

Probe #2

Can you change a property from configurable: false back to configurable: true?

Probe #3

Why does Object.assign() fail to copy getters and setters properly, and how does Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) solve this?