Proxy and Reflect
Proxy intercepts fundamental object operations through traps; Reflect provides each operation's default implementation for a trap to delegate to.
new Proxy(target, handler) / Reflect.get/set/has/deleteProperty(...)
Purpose
A Proxy wraps a target object and intercepts fundamental operations (property get/set,
has/in, deleteProperty, and more) through handler functions called traps. Reflect provides
the default implementation of each such operation as a plain callable function.
Syntax
const handler = {
get(target, prop, receiver) {
console.log(`Reading ${String(prop)}`);
return Reflect.get(target, prop, receiver);
},
set(target, prop, value, receiver) {
if (prop === 'age' && value < 0) throw new TypeError('age must be non-negative');
return Reflect.set(target, prop, value, receiver);
},
};
const user = new Proxy({ name: 'Ada', age: 30 }, handler);
Behavior notes
- A trap that isn’t defined in the handler falls back to the target’s default behavior
automatically — a
Proxyonly needs to define the traps it actually wants to customize. - Certain invariants are enforced regardless of trap logic — a
gettrap cannot report a different value than a non-configurable, non-writable property’s actual value; violating an invariant throws aTypeErrorautomatically. Reflect’s methods mirror the low-level operationsProxytraps intercept, one-to-one — usingReflect.setinside asettrap, rather thantarget[prop] = value, correctly passes through thereceiverargument, which matters for inherited proxies.- Every trapped operation adds overhead compared to plain object access, and makes the object’s
behavior opaque to simple inspection (
console.log, a debugger) — a real cost to weigh against the interception’s benefit.
Common mistakes
- Reaching for a
Proxyfor simple validation where a factory function with explicit getter/setter methods would be easier to debug and reason about statically. - Forgetting to pass
receiverthrough in aset/gettrap when delegating toReflect, breaking correct behavior for a proxy used as another object’s prototype.
Runtime notes
Core ECMAScript (ES2015), identical behavior across every current browser and Node version, though performance characteristics can differ between engines.