Introduction to Object.defineProperty, Proxy, and Reflect in JavaScript

Object.defineProperty

An object in JavaScript is an unordered collection of key-value pairs, where each property can hold any type of value. While properties can be modified using literal notation, Object.defineProperty alows for defining new properties or modifying existing ones with specific characteristics.

Syntax:

Object.defineProperty(obj, prop, descriptor)

Parameters:

  • obj: Required. The target object.
  • prop: Required. The name of the property to define or modify.
  • descriptor: Required. The descriptor object defining the property's attributes.

Return Value: The object past as the first argument (obj).

Data Descriptors

When defining or modifying a property, you can specify data attributes:

Object.defineProperty({}, 'propertyName', {
    value: '', // The value of the property, can be any type, defaults to undefined
    writable: true, // Whether the value can be reassigned, true allows, false prevents, default false
    configurable: true, // Whether the property's attributes can be changed or deleted, true allows, false prevents
    enumerable: true // Whether the property appears in enumerations, true includes, false excludes
});

Accessor Descriptors

For properties with getter and setter methods, use accessor descriptors:

Object.defineProperty({}, 'propertyName', {
    get: function() { /* Called when property is accessed */ },
    set: function(value) { /* Called when property is assigned a value */ },
    configurable: true,
    enumerable: true
});

Note: When using get or set, the writable and value attributes are not allowed.

Proxy

Proxy creates a layer of interception around a target object, allowing you to filter and modify external access to the object. It acts as a proxy for operations on the target.

Syntax:

const proxy = new Proxy(target, handler);

Parameters:

  • target: The object to intercept.
  • handler: An object that defines the interception behavior.

Proxy enables interception of fundamental operations such as property lookup, assignment, enumeration, and function invocation.

Interception Methods: Proxy provides 13 interception methods:

  • get(): Intercepts property reads (e.g., proxy.property).
  • set(): Intercepts property assignments (e.g., proxy.property = value), returns a boolean.
  • getPrototypeOf(): Intercepts Object.getPrototypeOf(proxy), returns an object.
  • setPrototypeOf(): Intercepts Object.setPrototypeOf(proxy, proto), returns a boolean.
  • has(): Intercepts property in proxy, returns a boolean.
  • defineProperty(): Intercepts Object.defineProperty(proxy, property, descriptor), returns a boolean.
  • deleteProperty(): Intercepts delete proxy[property], returns a boolean.
  • apply(): Intercepts functon calls on the proxy (e.g., proxy(...args)).
  • construct(): Intercepts constructor calls (e.g., new Proxy(...args)).
  • ownKeys(): Intercepts property enumeration methods, returns an array.
  • getOwnPropertyDescriptor(): Intercepts Object.getOwnPropertyDescriptor(proxy, property), returns a descriptor object.
  • preventExtensions(): Intercepts Object.preventExtensions(proxy), returns a boolean.
  • isExtensible(): Intercepts Object.isExtensible(proxy), returns a boolean.

Proxy.revocable()

The Proxy.revocable() method returns a revocable Proxy instance:

const target = {};
const handler = {};
const { proxy, revoke } = Proxy.revocable(target, handler);

proxy.someProperty = 123;
console.log(proxy.someProperty); // 123

revoke();
console.log(proxy.someProperty); // TypeError: Revoked

This is useful for scenarios where access to a target object should be temporary or controlled.

Reflect

Design Goals:

  1. Move internal language methods from Object to Reflect (e.g., Object.defineProperty).
  2. Improve the return values of certain Object methods for better consistency (e.g., Reflect.defineProperty returns false on failure instead of throwing).
  3. Convert imperative Object operations into function calls (e.g., Reflect.has(obj, name) instead of name in obj).
  4. Provide methods that correspond one-to-one with Proxy interception methods, allowing Proxies to easily invoke default behaviors.

Example with Proxy:

const targetObject = {};
const proxyInstance = new Proxy(targetObject, {
    get(target, property) {
        console.log('Intercepted property access');
        return Reflect.get(target, property);
    },
    deleteProperty(target, property) {
        return Reflect.deleteProperty(target, property);
    },
    has(target, property) {
        return Reflect.has(target, property);
    }
});

Reflect Static Methods: Reflect includes 13 static methods that mirror Proxy interception methods:

  • Reflect.apply(target, thisArg, args)
  • Reflect.construct(target, args)
  • Reflect.get(target, name, receiver)
  • Reflect.set(target, name, value, receiver)
  • Reflect.defineProperty(target, name, desc)
  • Reflect.deleteProperty(target, name)
  • Reflect.has(target, name)
  • Reflect.ownKeys(target)
  • Reflect.isExtensible(target)
  • Reflect.preventExtensions(target)
  • Reflect.getOwnPropertyDescriptor(target, name)
  • Reflect.getPrototypeOf(target)
  • Reflect.setPrototypeOf(target, prototype)

These methods generally match the functionality of their Object counterparts and align with Proxy's interception capabilities.

Tags: javascript Object.defineProperty Proxy Reflect Metaprogramming

Posted on Fri, 05 Jun 2026 17:47:23 +0000 by Sweets287