Object Property Descriptors and Object Methods
Object Property Descriptors & Advanced Methods
Configurable, enumerable, writable attributes, accessors (getters/setters), and integrity seals.
The High-Security Digital Safe Lock
Property descriptors define the internal attributes of object properties in JavaScript. They grant granular control over mutability, visibility in iteration, and accessor behaviors.
Data Descriptors vs Accessor Descriptors
Data descriptors have `value` and `writable`. Accessor descriptors have `get` and `set` functions. Both share `enumerable` and `configurable`.
The Descriptor Attributes
1) `writable`: property value can be reassigned. 2) `enumerable`: appears in `for...in` and `Object.keys()`. 3) `configurable`: descriptor can be modified and property deleted.
Defining and Inspecting Descriptors
`Object.defineProperty(obj, prop, descriptor)` defines properties. `Object.getOwnPropertyDescriptor(obj, prop)` reads the descriptor attributes.
Object Integrity Levels
`Object.preventExtensions(obj)`: no new properties. `Object.seal(obj)`: prevents adding/deleting properties (configurable: false). `Object.freeze(obj)`: prevents adding, deleting, or mutating values (writable: false, configurable: false).
Creating non-enumerable, read-only properties with Object.defineProperty:
const user = { username: "charlie" };
// Defining a private, read-only ID property
Object.defineProperty(user, "id", {
value: "USER-9942",
writable: false, // Cannot be changed
enumerable: false, // Hidden from loops and Object.keys
configurable: false // Cannot be deleted or re-configured
});
console.log("Direct access:", user.id); // "USER-9942"
console.log("Object.keys:", Object.keys(user)); // Only ["username"]
// Attempting mutation
// user.id = "HACKED"; // In strict mode throws TypeError
console.log("Value remains safe:", user.id);
// Inspecting attributes
const descriptor = Object.getOwnPropertyDescriptor(user, "id");
console.log("Descriptor attributes:", {
writable: descriptor.writable,
enumerable: descriptor.enumerable,
configurable: descriptor.configurable
});
Direct access: USER-9942
Object.keys: [ 'username' ]
Value remains safe: USER-9942
Descriptor attributes: { writable: false, enumerable: false, configurable: false }
Omitted Descriptor Flags Default to False
The Risk: When defining properties with `Object.defineProperty()`, any omitted flag (`writable`, `enumerable`, `configurable`) defaults to `false`. When using `{ a: 1 }` object literals, they default to `true`!
The Fix: Always explicitly specify `writable: true, enumerable: true, configurable: true` unless you intentionally want restrictive locking.
- ✓ `writable`: Can value be changed? `enumerable`: Shows in `Object.keys()`? `configurable`: Can be deleted or modified?
- ✓ `Object.defineProperty()` flags default to `false` if omitted.
- ✓ `Object.freeze()` sets all existing properties to `writable: false, configurable: false`.
- ✓ `Object.seal()` prevents adding or deleting properties, but existing writable properties can still be modified.
- ✓ Use `Object.hasOwn(obj, prop)` for safe, unpollutable own property checks.