JS Object Protection
In this page:
Object.freeze(object);
Object.seal(object);
Object.preventExtensions(object);
Object.defineProperty(object, "property", { writable: false });
Freezing an Object with Object.freeze()
Object.freeze(obj) locks an object completely -- no properties can be added, removed, or have their values changed afterward.
It is commonly used for values meant to represent constants or fixed configuration that should never be accidentally modified.
Example: Freezing an Object with Object.freeze()
const config = Object.freeze({ apiUrl: "/api" });
config.apiUrl = "/changed"; // silently fails
console.log(config.apiUrl);
Checking If an Object Is Frozen
Object.isFrozen(obj) returns true if the object has been frozen, letting code check this state before deciding whether to attempt a modification, or for debugging why an expected mutation did not take effect.
Example: Checking If an Object Is Frozen
const obj = Object.freeze({ a: 1 });
console.log(Object.isFrozen(obj));
Sealing an Object with Object.seal()
Object.seal(obj) is a lighter restriction than freeze -- it prevents adding new properties or removing existing ones, but still allows changing the value of properties that already exist, useful when an object's shape should stay fixed while its data can still update.
Example: Sealing an Object with Object.seal()
const user = Object.seal({ name: "Sam" });
user.name = "Amit"; // allowed, value can change
// user.age = 30; // not allowed, cannot add new property
console.log(user);
The Shallow Nature of freeze() and seal()
Both Object.freeze() and Object.seal() only protect an object's own direct properties -- if one of those properties holds a nested object, that nested object remains completely unprotected and freely mutable, unless it is separately frozen or sealed too.
Example: The Shallow Nature of freeze() and seal()
const obj = Object.freeze({ nested: { value: 1 } });
obj.nested.value = 99; // still works! nested object is not frozen
console.log(obj.nested.value);
Choosing Between freeze(), seal(), and Neither
Use Object.freeze() for genuinely constant, fixed data (like an enum-style configuration); Object.seal() for data whose shape should stay fixed but whose values legitimately change; and leave an object entirely unrestricted when neither guarantee is actually needed.
Example: Choosing Between freeze(), seal(), and Neither
const MAX_USERS = Object.freeze({ limit: 100 }); // truly constant
const settings = Object.seal({ theme: "dark" }); // shape fixed, values can change
const data = { count: 0 }; // fully mutable
settings.theme = "light";
console.log(MAX_USERS, settings, data);
- Assuming Object.freeze() makes an object's nested objects immutable too -- like Object.assign() and spread, freeze() is shallow, only protecting the object's own direct properties.
- Expecting an attempted mutation of a frozen object to always throw an error -- outside strict mode, the mutation silently fails instead, which can hide a bug rather than surfacing it.
- Confusing Object.freeze() (locks everything: no add, remove, or change) with Object.seal() (allows changing existing values, but not adding or removing properties).
- Object.freeze(obj) prevents adding, removing, or changing any of an object's own properties.
- Object.seal(obj) prevents adding or removing properties, but still allows changing the values of existing ones.
- Both freeze() and seal() are shallow -- nested objects remain fully mutable unless frozen or sealed individually.
Object.freeze() and Object.seal() have been supported in every browser since ES5.
Chapter Quiz — Complete all 10 topics to unlock
0/10 topics done
Complete these topics first: