handler.defineProperty()
        
        
          
                Baseline
                
                  Widely available
                
                
              
        
        
        
          
                
              
                
              
                
              
        
        
      
      This feature is well established and works across many devices and browser versions. It’s been available across browsers since September 2016.
The handler.defineProperty() method is a trap for the [[DefineOwnProperty]] object internal method, which is used by operations such as Object.defineProperty().
Try it
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" property
Syntax
new Proxy(target, {
  defineProperty(target, property, descriptor) {
  }
})
Parameters
The following parameters are passed to the defineProperty() method. this is bound to the handler.
- target
- 
The target object. 
- property
- 
A string or Symbolrepresenting the property name.
- descriptor
- 
The descriptor for the property being defined or modified. 
Return value
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.
Description
>Interceptions
This trap can intercept these operations:
Or any other operation that invokes the [[DefineOwnProperty]] internal method.
Invariants
The proxy's [[DefineOwnProperty]] internal method throws a TypeError if the handler definition violates one of the following invariants:
- A property cannot be added, if the target object is not extensible. That is, if Reflect.isExtensible()returnsfalseontarget, andReflect.getOwnPropertyDescriptor()returnsundefinedfor the property ontarget, then the trap must return a falsy value.
- A property cannot be non-configurable, unless there exists a corresponding non-configurable own property of the target object. That is, if Reflect.getOwnPropertyDescriptor()returnsundefinedorconfigurable: truefor the property ontarget, anddescriptor.configurableisfalse, then the trap must return a falsy value.
- A non-configurable property cannot be non-writable, unless there exists a corresponding non-configurable, non-writable own property of the target object. That is, if Reflect.getOwnPropertyDescriptor()returnsconfigurable: false, writable: truefor the property ontarget, anddescriptor.writableisfalse, then the trap must return a falsy value.
- If a property has a corresponding property on the target object, then the target object property's descriptor must be compatible with descriptor. That is, pretendingtargetis an ordinary object, andObject.defineProperty(target, property, descriptor)would throw an error, then the trap must return a falsy value. TheObject.defineProperty()reference contains more information, but to summarize, when the target property is non-configurable, the following must hold:- configurable,- enumerable,- get, and- setcannot be changed
- the property cannot be switched between data and accessor
- the writableattribute can only be changed fromtruetofalse
- the valueattribute can only be changed ifwritableistrue
 
Examples
>Trapping of defineProperty
The 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):
- enumerable
- configurable
- writable
- value
- get
- set
const 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' }
Specifications
| Specification | 
|---|
| ECMAScript® 2026 Language Specification> # sec-proxy-object-internal-methods-and-internal-slots-defineownproperty-p-desc> | 
Browser compatibility
Loading…