The handler.defineProperty() method is a trap for the [[DefineOwnProperty]] object internal method, which is used by operations such as Object.defineProperty().
const handler = {
defineProperty(target, key, descriptor) {
invariant(key, "define");
return true;
},
};
function invariant(key, action) {
if (key[0] === "_") {
throw new Error(`Invalid attempt to ${action} private "${key}" property`);
}
}
const monster = {};
const proxy = new Proxy(monster, handler);
console.log((proxy._secret = "easily scared"));
// Expected output: Error: Invalid attempt to define private "_secret" propertynew Proxy(target, {
defineProperty(target, property, descriptor) {
}
})The following parameters are passed to the defineProperty() method. this is bound to the handler.
targetThe target object.
propertyA string or Symbol representing the property name.
descriptorThe descriptor for the property being defined or modified.
The defineProperty() method must return a Boolean indicating whether or not the property has been successfully defined. Other values are coerced to booleans.
Many operations, including Object.defineProperty() and Object.defineProperties(), throw a TypeError if the [[DefineOwnProperty]] internal method returns false.
This trap can intercept these operations:
Or any other operation that invokes the [[DefineOwnProperty]] internal method.
The proxy's [[DefineOwnProperty]] internal method throws a TypeError if the handler definition violates one of the following invariants:
Reflect.isExtensible() returns false on target, and Reflect.getOwnPropertyDescriptor() returns undefined for the property on target, then the trap must return a falsy value.Reflect.getOwnPropertyDescriptor() returns undefined or configurable: true for the property on target, and descriptor.configurable is false, then the trap must return a falsy value.Reflect.getOwnPropertyDescriptor() returns configurable: false, writable: true for the property on target, and descriptor.writable is false, then the trap must return a falsy value.descriptor. That is, pretending target is an ordinary object, and Object.defineProperty(target, property, descriptor) would throw an error, then the trap must return a falsy value. The Object.defineProperty() reference contains more information, but to summarize, when the target property is non-configurable, the following must hold:configurable, enumerable, get, and set cannot be changedwritable attribute can only be changed from true to falsevalue attribute can only be changed if writable is trueThe following code traps Object.defineProperty().
const p = new Proxy(
{},
{
defineProperty(target, prop, descriptor) {
console.log(`called: ${prop}`);
return true;
},
},
);
const desc = { configurable: true, enumerable: true, value: 10 };
Object.defineProperty(p, "a", desc); // "called: a"When calling Object.defineProperty() or Reflect.defineProperty(), the descriptor passed to defineProperty() trap has one restriction—only following properties are usable (non-standard properties will be ignored):
enumerableconfigurablewritablevaluegetsetconst p = new Proxy(
{},
{
defineProperty(target, prop, descriptor) {
console.log(descriptor);
return Reflect.defineProperty(target, prop, descriptor);
},
},
);
Object.defineProperty(p, "name", {
value: "proxy",
type: "custom",
}); // { value: 'proxy' }