JavaScript Object.seal() Method: Sealing Objects
The Object.seal()
method in JavaScript is used to prevent new properties from being added to an object and marks all existing properties as non-configurable. This means that the properties cannot be deleted or reconfigured (e.g., changing their enumerability, configurability, or writability). However, values of existing properties can still be changed as long as they are writable.
Purpose of Object.seal()
The primary purpose of Object.seal()
is to create objects that have a fixed structure. This is useful when you want to ensure that an object’s properties remain consistent and cannot be altered structurally during its lifecycle. This provides a level of immutability without completely freezing the object.
Syntax
Object.seal(obj)
Parameters
obj
: The object which should be sealed.
Return Value
The sealed object.
Characteristics of a Sealed Object
- Preventing Property Addition: No new properties can be added to the object.
- Non-Configurable Properties: Existing properties cannot be deleted or reconfigured.
- Writable Properties: Values of writable properties can still be changed.
- Enumerable Properties: Enumerability of existing properties is preserved.
Examples of Using Object.seal()
Let’s explore several examples to illustrate how Object.seal()
works in practice.
Basic Sealing Example
In this example, we’ll seal a simple object and attempt to add a new property, which will fail in strict mode.
"use strict";
const objSeal1 = {
property1: "value1",
property2: "value2",
};
Object.seal(objSeal1);
objSeal1.property1 = "new value"; // This will work
try {
objSeal1.property3 = "value3"; // This will fail in strict mode
} catch (e) {
console.log(e); // Outputs: TypeError: Cannot add property property3, object is not extensible
}
console.log(objSeal1); // Outputs: { property1: 'new value', property2: 'value2' }
console.log(Object.isSealed(objSeal1)); // Outputs: true
Output:
TypeError: Cannot add property property3, object is not extensible
{ property1: 'new value', property2: 'value2' }
true
Preventing Deletion of Properties
This example demonstrates that properties of a sealed object cannot be deleted.
"use strict";
const objSeal2 = {
property1: "value1",
property2: "value2",
};
Object.seal(objSeal2);
try {
delete objSeal2.property1; // This will fail in strict mode
} catch (e) {
console.log(e); // Outputs: TypeError: Cannot delete property 'property1' of #<Object>
}
console.log(objSeal2); // Outputs: { property1: 'value1', property2: 'value2' }
Output:
TypeError: Cannot delete property 'property1' of #<Object>
{ property1: 'value1', property2: 'value2' }
Modifying Writable Properties
This example shows that you can still modify the values of writable properties in a sealed object.
const objSeal3 = {
property1: "value1",
property2: "value2",
};
Object.seal(objSeal3);
objSeal3.property1 = "new value"; // This will work
console.log(objSeal3); // Outputs: { property1: 'new value', property2: 'value2' }
Output:
{ property1: 'new value', property2: 'value2' }
Attempting to Reconfigure Properties
In this example, we attempt to reconfigure a property, which will fail because sealed object properties are non-configurable.
"use strict";
const objSeal4 = {
property1: "value1",
};
Object.seal(objSeal4);
try {
Object.defineProperty(objSeal4, "property1", { writable: false }); // This will fail in strict mode
} catch (e) {
console.log(e); // Outputs: TypeError: Cannot redefine property: property1
}
console.log(objSeal4); // Outputs: { property1: 'value1' }
Output:
TypeError: Cannot redefine property: property1
{ property1: 'value1' }
Sealing an Already Frozen Object
If an object is already frozen, sealing it has no effect because frozen objects are already sealed and have immutable properties.
const objSeal5 = {
property1: "value1",
};
Object.freeze(objSeal5); // Object is now frozen
Object.seal(objSeal5); // Sealing has no additional effect
console.log(Object.isSealed(objSeal5)); // Outputs: true (because it's frozen)
console.log(Object.isFrozen(objSeal5)); // Outputs: true
Output:
true
true
Deep Sealing
Object.seal()
only performs a shallow seal. If an object contains properties that are themselves objects, these nested objects are not sealed. To achieve a deep seal, you need to recursively seal all nested objects.
function deepSeal(obj) {
if (typeof obj === "object" && obj !== null) {
Object.seal(obj);
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
deepSeal(obj[key]); // Recursive call
}
}
}
return obj;
}
const objSeal6 = {
property1: {
nestedProperty: "nestedValue",
},
};
deepSeal(objSeal6);
console.log(Object.isSealed(objSeal6)); // Outputs: true
console.log(Object.isSealed(objSeal6.property1)); // Outputs: true
Output:
true
true
Practical Use Case: Configuration Objects
Consider a configuration object that defines the settings for an application. Sealing this object can prevent accidental modifications to its structure, ensuring the application behaves as expected.
const configSeal = {
apiUrl: "https://api.example.com",
timeout: 5000,
maxRetries: 3,
};
Object.seal(configSeal);
// Attempting to add a new property will fail
try {
configSeal.cacheEnabled = true;
} catch (e) {
console.log(e); // Outputs: TypeError: Cannot add property cacheEnabled, object is not extensible
}
console.log(configSeal);
Output:
TypeError: Cannot add property cacheEnabled, object is not extensible
{ apiUrl: 'https://api.example.com', timeout: 5000, maxRetries: 3 }
Key Differences between seal(), freeze(), and preventExtensions()
Understanding the differences between seal()
, freeze()
, and preventExtensions()
is crucial for choosing the right method for different scenarios:
Object.seal()
:- Prevents adding new properties.
- Marks existing properties as non-configurable (cannot be deleted or reconfigured).
- Allows changing the values of existing writable properties.
Object.freeze()
:- Prevents adding new properties.
- Marks existing properties as non-configurable.
- Prevents changing the values of existing properties (makes them read-only).
Object.preventExtensions()
:- Prevents adding new properties.
- Allows deleting existing properties.
- Allows reconfiguring existing properties.
- Allows changing the values of existing writable properties.
Here’s a table summarizing the differences:
Feature | Object.seal() |
Object.freeze() |
Object.preventExtensions() |
---|---|---|---|
Prevent Adding Properties | Yes | Yes | Yes |
Prevent Deleting Properties | Yes | Yes | No |
Prevent Reconfiguring Properties | Yes | Yes | No |
Prevent Changing Property Values | No (if writable) | Yes | No (if writable) |
Checking if an Object is Sealed
You can use Object.isSealed()
to determine whether an object is sealed.
const objSeal7 = {
property1: "value1",
};
console.log(Object.isSealed(objSeal7)); // Outputs: false
Object.seal(objSeal7);
console.log(Object.isSealed(objSeal7)); // Outputs: true
Output:
false
true
Browser Support
The Object.seal()
method is widely supported across modern web browsers. Hereβs a summary of browser compatibility:
- Chrome: Version 4+
- Firefox: Version 4+
- Safari: Version 5.1+
- Edge: Version 12+
- Opera: Version 12+
- Internet Explorer: Version 9+
Conclusion
The Object.seal()
method in JavaScript provides a useful mechanism for creating objects with a fixed structure, preventing structural modifications while still allowing property values to be updated. This offers a balance between immutability and flexibility, making it suitable for various use cases, such as configuration objects and data models where structural integrity is important. Understanding the nuances of seal()
and how it differs from freeze()
and preventExtensions()
allows you to choose the right approach for managing object immutability in your JavaScript applications. π‘οΈ