JS Proxy and Reflect
In this page:
const proxy = new Proxy(target, {
get(target, property) {
return Reflect.get(target, property);
}
});
Proxy Basics
A Proxy lets you intercept operations on an object. A handler defines what should happen. Common traps include get, set, has, and deleteProperty, each corresponding to a fundamental operation you can observe or override on the wrapped object.
Example: Proxy Basics
// Declare the constant `handler`; its value is built below
// Declare the constant `handler`; its value is built below
const handler = {
// Define the method `get` taking `target`, `prop`
// Define the method `get` taking `target`, `prop`
get(target, prop) {
// Print `"Reading:", prop` to the console
// Print `"Reading:", prop` to the console
console.log("Reading:", prop);
// Return `target[prop]` from this function
// Return `target[prop]` from this function
return target[prop];
},
};
// Declare the constant `obj` as a new `Proxy` instance
// Declare the constant `obj` as a new `Proxy` instance
const obj = new Proxy({ name: "Sam" }, handler);
// Print `obj.name` to the console
// Print `obj.name` to the console
console.log(obj.name);
Intercepting Property Changes
The set trap runs when a property is assigned through the Proxy. Without a set trap, changes to the proxy fall straight through to the underlying object; with one, you can log, validate, or reject the change before it happens.
Example: Intercepting Property Changes
// Declare the constant `handler`; its value is built below
// Declare the constant `handler`; its value is built below
const handler = {
// Define the method `set` taking `target`, `prop`, `value`
// Define the method `set` taking `target`, `prop`, `value`
set(target, prop, value) {
// Print `"Setting", prop, "to", value` to the console
// Print `"Setting", prop, "to", value` to the console
console.log("Setting", prop, "to", value);
target[prop] = value;
// Return `true` from this function
// Return `true` from this function
return true;
},
};
// Declare the constant `obj` as a new `Proxy` instance
// Declare the constant `obj` as a new `Proxy` instance
const obj = new Proxy({}, handler);
// Assign `30` to `obj.age`
// Assign `30` to `obj.age`
obj.age = 30;
Using Reflect
Reflect provides standard methods for object operations. It works well inside Proxy traps.
Reflect's methods mirror the default behavior a trap would otherwise need to reimplement manually, so calling Reflect.get/set inside a trap lets you extend rather than replace default behavior.
Example: Using Reflect
// Declare the constant `handler`; its value is built below
// Declare the constant `handler`; its value is built below
const handler = {
// Define the method `get` taking `target`, `prop`
// Define the method `get` taking `target`, `prop`
get(target, prop) {
// Return `Reflect.get(target, prop)` from this function
// Return `Reflect.get(target, prop)` from this function
return Reflect.get(target, prop);
},
};
// Declare the constant `obj` as a new `Proxy` instance
// Declare the constant `obj` as a new `Proxy` instance
const obj = new Proxy({ name: "Sam" }, handler);
// Print `obj.name` to the console
// Print `obj.name` to the console
console.log(obj.name);
Validation with Proxy
A Proxy can validate values before storing them. Throwing or returning false from inside a set trap (paired with Reflect.set for the valid cases) lets you enforce constraints, like requiring a property stay within an allowed range.
Example: Validation with Proxy
// Declare the constant `handler`; its value is built below
// Declare the constant `handler`; its value is built below
const handler = {
// Define the method `set` taking `target`, `prop`, `value`
// Define the method `set` taking `target`, `prop`, `value`
set(target, prop, value) {
// Check whether `prop === "age" && value < 0`
// Check whether `prop === "age" && value < 0`
if (prop === "age" && value < 0) {
// Throw a new `RangeError` with message "Age cannot be negative"
// Throw a new `RangeError` with message "Age cannot be negative"
throw new RangeError("Age cannot be negative");
}
// Return `Reflect.set(target, prop, value)` from this function
// Return `Reflect.set(target, prop, value)` from this function
return Reflect.set(target, prop, value);
},
};
// Declare the constant `user` as a new `Proxy` instance
// Declare the constant `user` as a new `Proxy` instance
const user = new Proxy({}, handler);
// Assign `30` to `user.age`
// Assign `30` to `user.age`
user.age = 30;
// Print `user.age` to the console
// Print `user.age` to the console
console.log(user.age);
Practical Proxy Example
Proxy is useful for logging, validation, defaults, and controlled access to object properties.
Because traps run for every relevant operation, Proxy is useful for building reactive systems, ORMs, and API wrappers that need to react to arbitrary property access transparently.
Example: Practical Proxy Example
// Declare the constant `handler`; its value is built below
// Declare the constant `handler`; its value is built below
const handler = {
// Define the method `get` taking `target`, `prop`
// Define the method `get` taking `target`, `prop`
get(target, prop) {
// Print `Accessed ${prop}` to the console
// Print `Accessed ${prop}` to the console
console.log(`Accessed ${prop}`);
// Return `Reflect.get(target, prop)` from this function
// Return `Reflect.get(target, prop)` from this function
return Reflect.get(target, prop);
},
};
// Declare the constant `logged` as a new `Proxy` instance
// Declare the constant `logged` as a new `Proxy` instance
const logged = new Proxy({ id: 1 }, handler);
// Print `logged.id` to the console
// Print `logged.id` to the console
console.log(logged.id);
- Forgetting to
return truefrom asettrap in strict mode, which throwsTypeError. - Changing the original target directly and expecting the proxy traps to run, when only access through the proxy is intercepted.
- Writing traps that call
proxy[prop]and cause infinite recursion; useReflect.get(target, prop).
- The prototype chain and prototypal inheritance describe how objects share properties in JavaScript.
Object.createand mixins build objects and share behavior.WeakMap,WeakSet,Proxy, andReflectoffer advanced object features.
Chapter Quiz — Complete all 6 topics to unlock
0/6 topics done
Complete these topics first: