JS TutorialLesson #258

JavaScript Proxy

A Proxy is a JavaScript object that can wrap other objects.

What is a Proxy?

A Proxy is a JavaScript object that can wrap other objects.

A Proxy lets you control operations on other objects.

A Proxy can trap and intercept code when someone is:

  • Reading a property (get)
  • Setting a property (set)
  • Deleting a property (deleteProperty)
  • Checking if a property exists (has)
  • Calling a function (apply)
  • Constructing an object (construct)
A Proxy lets you run your own code when someone interacts with an object. > A Proxy gan be a middleman between your code and a JavaScript object.

Example

Example Code

javascript
Try it Yourself
const proxy = new Proxy(target, handler);
  • target - the original object or function
  • handler - an object with trap methods

Example

Example Code

javascript
Try it Yourself
const myObject = {name: "Jan"};

const proxy = new Proxy(myObject, {

  get(target, prop) {

    return target[prop];

  }

});

Proxy Logging

A typical Proxy example is logging of object changes.

Below is a demo that:

  • Wraps an object in a Proxy
  • Logs whenever a property is read or written
  • Logs each get and set operation in real time

Example

Example Code

javascript
Try it Yourself
// Create an Object

const user = { name: "Jan", age: 40 };

//Create a Proxy

const proxy = new Proxy(user, {

  get(target, property) {

    log("Getting: " + property);

    return target[property];

  },

  set(target, property, value) {

    log("Setting: " + property);

    return target[property];

  }

});

proxy.name = "John";

proxy.age = 42;

let text1 = proxy.name;

let text2 = proxy.age

Proxy with Reflect (Most Common)

Below is a demo that:

  • Wraps an object in a Proxy
  • Logs whenever a property is read or written
  • Uses Reflect.get() and Reflect.set() inside the Proxy handlers
  • get trap uses Reflect.get(target, property, receiver)
  • set trap uses Reflect.set(target, property, value, receiver)
  • Reflect makes the Proxy behavior match the normal object behavior

Example

Example Code

javascript
Try it Yourself
// Create an Object

const user = { name: "Jan", age: 40 };

// Create a Proxy

const proxy = new Proxy(user, {

  get(target, property) {

    log("Getting: " + property);
    // safe forwarding

    return Reflect.get(target, property);

  },

  set(target, property, value) {

    log("Setting: " + property);
    // safe forwarding

    return Reflect.set(target, property, value);

  }

});

proxy.name = "John";

proxy.age = 42;

let text1 = proxy.name;

let text2 = proxy.age

Proxy with Reflect Flow

The flow below is the essence of JavaScript metaprogramming with Proxy + Reflect.

Flow Explanation:

  • Your code interacts with an object
  • Proxy intercepts the operation
  • Your trap code decides what to do
  • Reflect forwards the operation safely
  • The target object receives the real action

Why Proxies?

Proxies allow you to:

  • Add logging
  • Validate changes
  • Auto-generate properties
  • Protect sensitive data
  • Create virtual or computed objects
  • Intercept function calls
  • Create reactive systems (like Vue.js)

Proxy Validation

Example

Example Code

javascript
Try it Yourself
// Create an Object

const user = { name: "Jan", age: 40 };

// Create a Proxy

const proxy = new Proxy(user, {

  set(target, prop, value) {

    if (prop === "age" && value   **Metaprogramming**
> Metaprogramming lets JavaScript:
> Intercept behavior
> Modify behavior
> Define new behavior
> Generate behavior dynamically
> It gives developers deep control over the language's inner workings.

---

## Proxy Traps

A trap is a function inside a Proxy handler.

It runs whenever a specific operation is performed on the Proxy.

Below is a complete and accurate explanation of every JavaScript Proxy trap, what triggers them, their parameters, and what they are expected to return.

| Trap Name | Triggered when |
| --- | --- |
| get | A property is read |
| set | A property is changed |
| has | Using the in operator |
| deleteProperty | A property is deleted |
| apply | A function is called |
| construct | An object is cretated (with new) |
| getOwnPropertyDescriptor | A property descriptor is retrieved |
| defineProperty | A property is defined |
| getPrototypeOf | A prototype is retrieved |
| setPrototypeOf | A prototype is set |
| isExtensible | Extensibility is checked |
| preventExtensions | Existenibility is prevented |
| ownKeys | Properties are listed |

> The list above is 2025-accurate and includes all 13 Proxy traps defined in ECMAScript.
> Each trap handler is decribed below.

---

## handler.get()

Triggered when a **property is read**:

### Example

javascript get(obj, prop, receiver) {

return Reflect.get(obj, prop, receiver);

}

Example Code

html
Try it Yourself
**Parameters**

- obj - the target object
- prop - the property being accessed
- receiver - the this value for getters (usually the proxy itself)

**Must Return**

- The property value

---

## handler.set()

Triggered when a **property is assigned a value**:

### Example

javascript set(obj, prop, value, receiver) {

return Reflect.set(obj, prop, value, receiver);

}

Example Code

html
Try it Yourself
#### Parameters

- obj - the target object
- prop - the property being set
- value - the new property value
- receiver - the object that received the assignment (usually the proxy)

#### Must Return

- true - if the assignment succeeded
- false - if the assignment failed

Throwing an error is also allowed.

---

## handler.has()

Intercepts the **in** operator.

### Example

javascript has(obj, prop) {

return Reflect.has(obj, prop);

}

Example Code

html
Try it Yourself
**Parameters**

- obj - the target object
- prop - the property being accessed
- receiver - the value of this for setters (usually the proxy itself)

**Must Return**

- true
- false

---

## handler.deleteProperty()

Intercepts the **delete** operator.

### Example

javascript deleteProperty(obj, prop) {

return Reflect.deleteProperty(obj, prop);

}

Example Code

html
Try it Yourself
**Parameters**

- obj - the target object
- prop - the property to delete

**Must Return**

- true - for sucess
- false - for failure

---

## handler.apply()

Triggered when a **function is called**:

### Example

javascript apply(func, thisArg, args) {

return Reflect.apply(func, this, args);

}

Example Code

html
Try it Yourself
**Parameters**

- func - the callable object (function)
- this - the this argument for the call
- args - the function arguments array

**Must Return**

- The return value of the function

---

## handler.construct

Intercepts the **new** operator.

### Example

javascript construct(obj, args, newTarget) {

return Reflect.construct(obj, args, newTarget);

}

Example Code

html
Try it Yourself
**Parameters**

- obj - the constructor object
- args - the array of arguments passed
- newTarget - the constructor

**Must Return**

- An Object (The new instance)

### Example

javascript const obj = {} // No trap

Object.create() // No trap

class User {};

new User(); // No trap

Example Code

html
Try it Yourself
---

## handler.getOwnPropertyDescriptor()

Intercepts property descriptor retrieval.

### Example

javascript getOwnPropertyDescriptor(obj, prop) {

return Reflect.getOwnPropertyDescriptor(obj, prop);

}

Example Code

html
Try it Yourself
**Parameters**

- obj - the target object
- prop - the property to describe

**Must Return**

- A property descriptor
- undefined

---

## handler.defineProperty()

Intercepts Object.defineProperty().

### Example

javascript defineProperty(obj, prop, descriptor) {

return Reflect.defineProperty(obj, prop, descriptor);

}

Example Code

html
Try it Yourself
**Parameters**

- obj - the target object
- prop - the property to describe
- descriptor - the property descriptor

**Must Return**

- true - if sucess
- false - if not

---

## handler.getPrototypeOf()

Intercepts prototype lookup.

### Example

javascript getPrototypeOf(obj) {

return Reflect.getPrototypeOf(obj);

}

Example Code

html
Try it Yourself
**Parameters**

- obj - the target object

**Must Return**

- An Object
- null

---

## handler.setPrototypeOf()

Intercepts setting the prototype.

### Example

javascript setPrototypeOf(obj, prototype) {

return Reflect.setPrototypeOf(obj, prototype);

}

Example Code

html
Try it Yourself
**Parameters**

- obj - the target object
- prototype - the new prototype or null

**Must Return**

- An Object
- null

---

## handler.isExtensible()

Intercepts checking if an object is extensible.

### Example

javascript isExtensible(obj) {

return Reflect.isExtensible(obj);

}

Example Code

html
Try it Yourself
**Parameters**

- obj - the target object

**Must Return**

- true - for yes
- false - for no

---

## handler.preventExtentions()

Intercepts making an object non-extensible.

### Example

javascript preventExtensions(obj) {

return Reflect.preventExtensions(obj);

}

Example Code

html
Try it Yourself
**Parameters**

- obj - the target object

**Must Return**

- true - for success
- false - for failure

---

## handler.ownKeys()

Intercepts operations listing keys (property names or symbols).

### Example

javascript ownKeys(obj) {

return Reflect.ownKeys(obj);

}

Example Code

html
Try it Yourself
**Parameters**

- obj - the target object

**Must Return**

- array of keys with no duplicates

---

## Proxy Traps Map Reflect Methods

A Proxy trap represents one of JavaScript's internal operations:

- [[Construct]]
- [[Call]]
- [[Get]]
- [[Set]]
- [[HasProperty]]
- [[Delete]]
- [[DefineProperty]]
- [[GetOwnProperty]]
- [[OwnPropertyKeys]]
- [[GetPrototypeOf]]
- [[SetPrototypeOf]]
- [[PreventExtensions]]
- [[IsExtensible]]

These internal operations are what JavaScript uses (inside the engine) when you access or modify objects.

When a Proxy intercepts one of these operations, they should be forwarded correctly:

### Example

javascript get(target, property, receiver) {

return Reflect.get(target, property, receiver);

} ```

Reflect is used because Reflect methods are 1-to-1 mirrors of the internal operations.

  • They produce correct return values (true/false/descriptor)
  • They avoid throwing errors that would break Proxy rules
  • They make the Proxy behave like normal JavaScript objects (unless modified)
This is why every Proxy trap has a Reflect method with the same name and signature.

JavaScript Internals Became Reflect

Before ES6 (2015), many fundamental operations did not exist as functions: | Operation | Before E6 | Problem | | --- | --- | --- | | get property | obj[prop] | Not callable as a function | | set property | obj[prop] = value | Not callable as a function | | delete property | delete obj[prop] | Operator, not a function | | check property | "prop" in obj | Operator, not a function | | construct (new) | new Foo() | Not callable generically | | get prototypes | Object.getPrototypeOf(obj) | Throws on non-objects | | define property | Object.defineProperty() | Returns object instead of boolean | | own keys | Object.keys() | Not complete (misses symbols) | These were incomplete and inconsistent for Proxy forwarding.

So ES6 (2015) added Reflect:

Internal OperationReflect Method
[[Construct]]Reflect.construct()
[[Call]]Reflect.apply()
[[Get]]Reflect.get()
[[Set]]Reflect.set()
[[HasProperty]]Reflect.has()
[[Delete]]Reflect.deleteProperty()
[[DefineProperty]]Reflect.defineProperty()
[[GetOwnProperty]]Reflect.getOwnProperty()
[[OwnPropertyKeys]]Reflect.ownPropertyKeys()
[[IsExstensible]]Reflect.isExtensible()
[[PreventExstensions]]Reflect.preventExtensions()
[[GetPrototypeOf]]Reflect.getPrototypeOf()
[[SetPrototypeOf]]Reflect.setPrototypeOf()
Learn More > JavaScript Metaprogramming > JavaScript Reflect Tutorial > JavaScript Meta Reference

Interactive Code Examples

Example 1

javascript
Try it Yourself
JavaScript syntax and algorithm demonstration.
const proxy = new Proxy(target, handler);

JS Example 2

javascript
Try it Yourself
JavaScript syntax and algorithm demonstration.
const myObject = {name: "Jan"};



const proxy = new Proxy(myObject, {

  get(target, prop) {

    return target[prop];

  }

});

JS Example 3

javascript
Try it Yourself
JavaScript syntax and algorithm demonstration.
// Create an Object

const user = { name: "Jan", age: 40 };



//Create a Proxy

const proxy = new Proxy(user, {

  get(target, property) {

    log("Getting: " + property);

    return target[property];

  },

  set(target, property, value) {

    log("Setting: " + property);

    return target[property];

  }

});



proxy.name = "John";

proxy.age = 42;



let text1 = proxy.name;

let text2 = proxy.age

JS Example 4

javascript
Try it Yourself
JavaScript syntax and algorithm demonstration.
// Create an Object

const user = { name: "Jan", age: 40 };



// Create a Proxy

const proxy = new Proxy(user, {

  get(target, property) {

    log("Getting: " + property);
    // safe forwarding

    return Reflect.get(target, property);

  },

  set(target, property, value) {

    log("Setting: " + property);
    // safe forwarding

    return Reflect.set(target, property, value);

  }

});



proxy.name = "John";

proxy.age = 42;



let text1 = proxy.name;

let text2 = proxy.age

JS Example 5

javascript
Try it Yourself
Interactive runnable JavaScript example from EA Academy.
Live Output Preview:

JS Example 6

javascript
Try it Yourself
JavaScript syntax and algorithm demonstration.
// Create an Object

const person = {

  first: "John",

  last:  "Doe"

};



// Create a Proxy

const virtual = new Proxy(person, {

  get(target, prop) {

    if (prop === "fullName") {

      return target.first + " " + target.last;

    }

    return Reflect.get(target, prop);

  }

});



let text = virtual.fullName; // "John Doe"