← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

Object Property Descriptors

javascript ES5 Advanced
debt(d8/e3/b3/t7)
d8 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'silent in production until users hit it' (d9), pulled to d8: detection_hints.automated is 'no' and there is no linter rule for descriptor flag defaults. A property accidentally created read-only or hidden fails silently (writable:false fails silently in sloppy mode, non-enumerable fields silently dropped from JSON.stringify), surfacing only when an update silently fails or serialization misbehaves.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3): quick_fix says to set writable, enumerable, configurable explicitly in the defineProperty descriptor object. This is a localized correction to the descriptor literal, slightly more than a one-line swap since multiple flags and call sites may need auditing.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3): applies_to web/node/library but in practice descriptors are used in specific metaprogramming/reflection spots rather than across every module. The component using defineProperty pays the cognitive cost; the rest of the codebase is largely unaffected unless configurable:false locks something needed elsewhere.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7): misconception states developers assume defineProperty defaults match normal assignment, but it defaults writable/enumerable/configurable all to false — the opposite of how plain property assignment behaves. This contradicts the intuition built from normal object property creation, making the obvious approach wrong.

About DEBT scoring →

Also Known As

defineProperty getOwnPropertyDescriptor property attributes writable enumerable configurable

TL;DR

Property descriptors define the hidden attributes of object properties - writable, enumerable, configurable, plus getters and setters.

Explanation

Getters and setters defined in object literal syntax produce accessor descriptors that are enumerable and configurable, whereas accessors defined in class bodies sit on the prototype and are non-enumerable (but still configurable).

Common Misconception

People assume Object.defineProperty defaults match normal assignment. In fact defineProperty defaults writable, enumerable, and configurable all to false, so an omitted flag creates a read-only, hidden, locked property.

Why It Matters

Descriptor flags control serialization, reassignment, and reconfiguration; getting them wrong creates silent update failures or accidentally exposes internal fields through JSON.stringify.

Common Mistakes

  • Forgetting that Object.defineProperty defaults all flags to false, creating an unexpectedly locked property.
  • Using spread or Object.assign to clone and losing getters, setters, and non-enumerable flags.
  • Assuming writable: false throws on reassignment in sloppy mode when it fails silently.
  • Setting configurable: false too early, then being unable to delete or redefine the property.
  • Expecting non-enumerable properties to be hidden from Object.getOwnPropertyNames or direct access.

Avoid When

  • Simple objects where normal assignment with default writable/enumerable/configurable is sufficient.
  • When the property model is well-served by class fields or plain object literals.
  • Hot paths where defineProperty per property adds avoidable overhead over direct assignment.

When To Use

  • Defining non-enumerable internal fields you want hidden from serialization and iteration.
  • Creating computed accessor properties with get/set on existing objects.
  • Cloning objects while preserving getters, setters, and exact descriptor flags.

Code Examples

✗ Vulnerable
config.timeout = 10000; // Silently ignored in sloppy mode; throws TypeError in strict mode/modules
console.log(config.timeout); // 5000
✓ Fixed
const config = {};

// Be explicit about every flag you care about:
Object.defineProperty(config, 'timeout', {
    value: 5000,
    writable: true,
    enumerable: true,
    configurable: true,
});

config.timeout = 10000;
console.log(config.timeout); // 10000
console.log(JSON.stringify(config)); // {"timeout":10000}

// Clone faithfully, preserving getters and flags:
const src = { get id() { return 42; } };
const copy = Object.create(
    Object.getPrototypeOf(src),
    Object.getOwnPropertyDescriptors(src)
);
console.log(Object.getOwnPropertyDescriptor(copy, 'id').get); // function

Added 1 Jun 2026
Views 5
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 3 pings M 1 ping T 0 pings W
No pings yet today
ChatGPT 1
ChatGPT 2 Google 1 Perplexity 1
crawler 3 crawler_json 1
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: Medium
⚡ Quick Fix
When using Object.defineProperty, always set writable, enumerable, and configurable explicitly instead of relying on the false defaults.
📦 Applies To
javascript ES5 web node library
🔗 Prerequisites
🔍 Detection Hints
Object\.defineProperty\s*\([^,]+,[^,]+,\s*\{[^}]*\}\s*\)
Auto-detectable: ✗ No
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: Medium ✗ Manual fix Fix: Medium Context: Function Tests: Update

✓ schema.org compliant