JavaScript Object Sealing: Preventing New Properties with Object.preventExtensions


  • Effect
    After using Object.preventExtensions(object), any attempt to add a new property to the object will result in a TypeError. Existing properties and their values can still be modified.
  • Purpose
    Controls the ability to add new properties to an object.

Key Points

  • Prototypal Properties
    It only affects the specific object you call it on. You can still add properties to the object's prototype chain.
  • Doesn't Freeze Entire Object
    Unlike Object.freeze(), preventExtensions only restricts adding new properties. Existing properties can still be modified (values changed) or deleted.

Example

const person = { name: "Alice", age: 30 };
Object.preventExtensions(person);

person.age = 31; // This works, modifying existing property
person.job = "Software Engineer"; // This throws a TypeError

console.log(person); // { name: "Alice", age: 31 }

In this example, even though we can't add new properties like job to person, we can still modify existing ones like age.

  • Data Validation
    When working with user input or external data, you might use preventExtensions to prevent unexpected properties from being added, potentially causing issues.
  • Protecting Object Integrity
    In situations where you want to ensure an object's structure remains fixed, preventExtensions can help prevent accidental additions.


Trying to Add a New Property After Prevention

const config = {
  apiKey: "your_api_key",
  apiUrl: "https://api.example.com"
};

Object.preventExtensions(config);

try {
  config.timeout = 10000; // This will throw a TypeError
} catch (error) {
  console.error("Error:", error.message);
}

console.log(config); // { apiKey: "your_api_key", apiUrl: "https://api.example.com" }

This code demonstrates that attempting to add a new property (timeout) after using preventExtensions throws a TypeError.

Modifying Existing Property

const product = {
  name: "T-Shirt",
  price: 19.99
};

Object.preventExtensions(product);

product.price = 24.99; // This works, modifying existing property

console.log(product); // { name: "T-Shirt", price: 24.99 }

This example shows that even after preventing extensions, you can still modify the values of existing properties like price.

Adding Properties to Prototype Chain

function User(name) {
  this.name = name;
}

const user1 = new User("Bob");
Object.preventExtensions(user1);

user1.age = 35; // This won't throw an error (property added to prototype)

User.prototype.occupation = "Developer";
user1.occupation; // "Developer" (accessible from prototype)

console.log(user1); // User { name: 'Bob' } (only shows own properties)

This code highlights that preventExtensions only affects the specific object. You can still add properties to the object's prototype chain, which user1 can then access.



  1. Object.freeze
    This method completely freezes an object, preventing any modifications. It achieves what preventExtensions does (stops adding new properties) and additionally makes existing properties non-writable (values cannot be changed), non-configurable (attributes cannot be changed), and prevents prototype reassignment. Use Object.freeze if you want complete immutability for your object.

  2. Object.seal
    This method seals an object, preventing new properties from being added and existing properties from being deleted. However, existing properties can still be modified (values changed). Use Object.seal if you want to enforce a fixed set of properties but allow modifications to their values.

  3. Object.defineProperty
    This method allows granular control over individual properties. You can define specific attributes like writable (false to prevent modification), configurable (false to prevent attribute changes), and enumerable (false to hide from loops). Use defineProperty for fine-grained control over specific properties within an object.

  4. Proxy Objects (ES6+)
    Proxy objects act as an intermediary between the original object and its operations. You can define custom behavior for property access, modification, and deletion. This offers more flexibility but can be more complex to set up compared to the other methods.

Choosing the Right Alternative

  • Desire flexibility and custom behavior
    Consider Proxy objects (for advanced use cases).
  • Need fine-grained control over individual properties
    Use Object.defineProperty.
  • Want to prevent adding properties but allow value changes
    Use Object.seal.
  • Need complete immutability
    Use Object.freeze.