Preventing Property Deletion with the deleteProperty
Trap
The delete
operator removes a property from an object and returns true
when successful and false
when unsuccessful. In strict mode, delete
throws an error when you attempt to delete a nonconfigurable property; in nonstrict mode, delete
simply returns false
. Here’s an example:
let target = {
name: "target",
value: 42
};
Object.defineProperty(target, "name", { configurable: false });
console.log("value" in target); // true
let result1 = delete target.value;
console.log(result1); // true
console.log("value" in target); // false
// Note: The following line throws an error in strict mode
let result2 = delete target.name;
console.log(result2); // false
console.log("name" in target); // true
The value
property is deleted using the delete
operator and, as a result, the in
operator returns false
in the third console.log()
call. The nonconfigurable name
property can’t be deleted so the delete
operator simply returns false
(if this code is run in strict mode, an error is thrown instead). You can alter this behavior by using the deleteProperty
trap in a proxy.
The deleteProperty
trap is called whenever the delete
operator is used on an object property. The trap is passed two arguments:
trapTarget
- the object from which the property should be deleted (the proxy’s target)key
- the property key (string or symbol) to delete
The Reflect.deleteProperty()
method provides the default implementation of the deleteProperty
trap and accepts the same two arguments. You can combine Reflect.deleteProperty()
and the deleteProperty
trap to change how the delete
operator behaves. For instance, you could ensure that the value
property can’t be deleted:
let target = {
name: "target",
value: 42
};
let proxy = new Proxy(target, {
deleteProperty(trapTarget, key) {
if (key === "value") {
return false;
} else {
return Reflect.deleteProperty(trapTarget, key);
}
}
});
// Attempt to delete proxy.value
console.log("value" in proxy); // true
let result1 = delete proxy.value;
console.log(result1); // false
console.log("value" in proxy); // true
// Attempt to delete proxy.name
console.log("name" in proxy); // true
let result2 = delete proxy.name;
console.log(result2); // true
console.log("name" in proxy); // false
This code is very similar to the has
trap example in that the deleteProperty
trap checks to see if the key
is "value"
and returns false
if so. Otherwise, the default behavior is used by calling the Reflect.deleteProperty()
method. The value
property can’t be deleted through proxy
because the operation is trapped, but the name
property is deleted as expected. This approach is especially useful when you want to protect properties from deletion without throwing an error in strict mode.