Lesson 56: Mastering JavaScript Property flags and descriptors with challenges!

π§© What Are Property Descriptors?
In JavaScript, every property in an object has attributes (a.k.a. property flags):
Flag | Meaning |
writable | Can the value be changed with assignment (= )? |
enumerable | Will it appear in for...in , Object.keys() , etc.? |
configurable | Can the property be deleted or reconfigured (flags changed)? |
By default, when a property is created using object literal {}
, all flags are true
.
β Access Descriptors
const user = { name: "Alice" };
console.log(Object.getOwnPropertyDescriptor(user, 'name'));
/*
{
value: 'Alice',
writable: true,
enumerable: true,
configurable: true
}
*/
β Define/Modify Descriptors
Object.defineProperty(user, 'name', {
writable: false,
configurable: false
});
This makes name
a constant β can't change or delete.
β Real-World Use
let settings = {};
Object.defineProperty(settings, 'version', {
value: '1.0.0',
writable: false,
enumerable: false,
configurable: false
});
π Descriptor Flowchart
ββββββββββββββ
β Define propβ
βββββββ¬βββββββ
β
ββββββββββββββββββββββββββΌβββββββββββββββββββββββββββ
βΌ βΌ βΌ
writable: false enumerable: false configurable: false
Can't assign Skipped in Can't delete
new value loops/keys() or redefine flags
πΉ 2. Fill Any Gaps
β
Defaults from defineProperty
If you omit any flags, they default to false
(not true
).
Object.defineProperty(obj, "a", { value: 10 });
// => a is now non-writable, non-enumerable, non-configurable
β Symbolic and Non-enumerable Properties
These do not appear in:
for...in
Object.keys()
But they do appear in:Object.getOwnPropertyDescriptors
Reflect.ownKeys()
β
You Canβt Revert configurable: false
Once you mark a property as configurable: false
, you cannot:
delete it
change
enumerable
change
configurable
againchange
writable
from false to true (but true β false is allowed)
β Shallow Cloning with Descriptors
let clone = Object.defineProperties({}, Object.getOwnPropertyDescriptors(source));
β
Includes non-enumerable and symbol keys.
β Doesnβt deep-clone nested objects.
β Strict Mode Behavior
'use strict';
Object.defineProperty(obj, 'x', { writable: false });
obj.x = 10; // β TypeError
Without 'use strict'
, this fails silently!
β Define Multiple Properties at Once
Object.defineProperties(user, {
name: { value: 'Alice', writable: false },
age: { value: 30, writable: true }
});
β Sealing / Freezing Objects
Method | Prevent Add | Prevent Delete | Prevent Write | Prevent Reconfig |
Object.preventExtensions() | β | β | β | β |
Object.seal() | β | β | β | β |
Object.freeze() | β | β | β | β |
πΉ 3. Challenge Me Deeply
π’ Basic
Define a property
secret
on an object that is not writable, not enumerable, and not configurable. Try modifying and deleting it.Use
Object.getOwnPropertyDescriptor()
to inspect a built-in object likeMath.PI
.Create a property
score
that is writable and enumerable but not configurable.
π‘ Intermediate
Write a function
makeConstant(obj, key, value)
that defines a constant property.Clone an object preserving all flags, including symbol keys.
Create an object with one enumerable property and one non-enumerable property. Use
for...in
andObject.keys()
to show the difference.
π΄ Advanced
Write a
deepFreeze(obj)
function that recursively freezes all nested properties.Create a descriptor-based
defineClassProperty(obj, key, value)
function that simulates a private class member (non-enumerable, non-writable).Try redefining a non-configurable property. Catch and explain the error.
Create a function
secureObject(obj)
that seals and logs all current property descriptors.
π― Aha! Brain-Twister
- You define a property with
writable: true, configurable: false
, then later changewritable
to false. Can you change it back to true? Why or why not?
πΉ 4. Interview-Ready Questions
β Concept Questions
What is the difference between
writable
,enumerable
, andconfigurable
?How does
Object.defineProperty()
differ from assigning properties directly?When do
Object.keys()
andfor...in
skip properties?
β Scenario-Based
How would you protect certain properties of a settings object from modification or deletion?
Youβre cloning an object but notice some properties are missing. Why might this happen?
β Debugging-Style
You defined a property using
defineProperty
, but assignment to it silently fails. What's likely the reason?You froze an object, yet a nested property was still modified. Why?
β Best Practices
β Do:
Use
Object.freeze()
for immutable config objects.Use
Object.defineProperties()
for grouped definitions.
β Donβt:
Mutate built-in objects like
Math
,Object.prototype
.Assume
for...in
shows all properties.
πΉ 5. Real-World Usage
π§ Library Authors: Use descriptors to define framework internals (e.g., Vueβs reactivity system).
π Security: Define read-only tokens or config properties.
π APIs: Hide internal implementation from public API (non-enumerable).
Example: Vue 3 Reactivity System
Object.defineProperty(obj, '__isReactive', {
value: true,
enumerable: false,
configurable: false
});
πΉ 6. Remember Like a Pro
π§ Mnemonic: WEC β βWe Eat Cookiesβ
Writable β Can you Write to it?
Enumerable β Will you Enumerate it?
Configurable β Can you Change or delete it?
π§Ύ Cheatsheet
Object.defineProperty(obj, 'x', {
value: 42,
writable: false, // can't change value
enumerable: false, // hidden from loops
configurable: false // can't delete or redefine
});
Scenario | Writable | Enumerable | Configurable |
Default literal | β | β | β |
defineProperty default | β | β | β |
πΉ 7. Apply It in a Fun Way
π― Mini Project: SecureConfig Builder
Build a utility to generate an app config object where all properties are:
Non-writable
Non-configurable
Optionally enumerable
β Steps:
Create a
createSecureConfig(configObj, isEnumerable = false)
function.Use
Object.defineProperties()
to lock down each key inconfigObj
.Add
Object.freeze()
to seal the object globally.
const config = createSecureConfig({ apiKey: "1234", debug: false });
config.apiKey = "9999"; // silently ignored or error in strict mode
β Extension
Add support for deep config freeze.
Include a getter/setter interface for internal changes (controlled).
π§ Optional β Extra Value
π Open Source Projects Using This
Vue.js (for reactivity markers)
Lodash (for internal method protection)
Express.js (on request/response objects)
β οΈ Common Mistakes
Forgetting that
defineProperty
defaults all flags to false!Expecting
Object.keys()
to show all properties, even non-enumerable ones.Assuming
delete obj.prop
always works β not forconfigurable: false
.
π Performance Tips
Avoid excessive use of
Object.defineProperty
in tight loops.Freezing large nested objects can be costly β use lazily.
β Polyfills / Alternatives
In older environments:
if (!Object.defineProperty) {
// Polyfill basic read-only functionality
}
Use libraries like Lodash _.defaultsDeep()
or deep-freeze utilities for safer immutable patterns.
Subscribe to my newsletter
Read articles from manoj ymk directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
