Object Extensibility in JavaScript
Introduction
JavaScript can lock down objects: prevent new properties, make existing ones read-only, or freeze everything. Object.preventExtensions, seal, and freeze help you build immutable config snapshots and catch accidental mutations early.
Prerequisites
Object.preventExtensions
No new properties; existing ones can still change:
const settings = { theme: "dark" };
Object.preventExtensions(settings);
settings.theme = "light";
settings.debug = true;
console.log(settings);Adding debug fails (strict mode throws).
Object.seal
Cannot add or remove properties; existing values can still be updated if writable:
const profile = { name: "Ada", role: "admin" };
Object.seal(profile);
profile.role = "editor";
delete profile.name;
console.log(profile);
console.log(Object.isSealed(profile));Object.freeze
Shallow freeze—no add/remove/change on top-level properties:
const constants = { MAX: 100, MIN: 0 };
Object.freeze(constants);
constants.MAX = 999;
constants.extra = 1;
console.log(constants);
console.log(Object.isFrozen(constants));Nested objects are not frozen deeply unless you freeze recursively.
Check State Helpers
const obj = {};
Object.preventExtensions(obj);
console.log(Object.isExtensible(obj));
console.log(Object.isSealed(obj));
console.log(Object.isFrozen(obj));When to Use
- Freeze — constants, lookup tables loaded once
- Seal — fixed shape records (known keys only)
- preventExtensions — stop growth but allow updates
Libraries like immer offer immutable updates without manual freeze in app state.
Mini Example: Frozen Feature Flags
const featureFlags = Object.freeze({
newCheckout: false,
betaApi: true,
});
function isEnabled(flag) {
return featureFlags[flag] === true;
}
console.log(isEnabled("betaApi"));FAQ
Deep freeze?
Loop and Object.freeze each nested object, or use a utility—freeze is shallow.
Can I unfreeze?
No—freeze is one-way unless you clone to a new object.
const vs freeze?
const stops rebinding the variable; the object can still mutate unless frozen.