Learn how Proxy traps and the Reflect API intercept and control object behavior in JavaScript.
Proxy wrappers to intercept standard operations.get and set to customize behaviors.Reflect API to forward default actions inside traps.Reflect methods inside every proxy trap to preserve default language behavior for properties.set trap to reject invalid assignments before updating targets.Reflect.get to keep getters bound to the correct context.Proxy wrapperWraps target objects using the Proxy constructor with custom handlers.
const target = { name: "Ada" };
const proxy = new Proxy(target, {});
console.log(proxy.name); // "Ada"Handler trapsSpecifies trap functions in handlers to intercept object reads.
const handler = {
get(target, prop) {
return target[prop];
}
};
const proxy = new Proxy({ x: 1 }, handler);Function proxyingWraps executable function objects to intercept call parameters.
function greet(name) { return `Hi ${name}`; }
const pr = new Proxy(greet, {
apply(t, thisArg, args) {
return t(...args);
}
});get trapIntercepts property access lookups and method executions.
const p = new Proxy({ a: 1 }, {
get(target, prop) {
return prop in target ? target[prop] : "missing";
}
});set trapIntercepts property assignments and returns confirmation flags.
const p = new Proxy({}, {
set(target, prop, value) {
target[prop] = value;
return true;
}
});has trapIntercepts the boolean property presence verification check.
const p = new Proxy({ secret: 1 }, {
has(target, prop) {
return prop === "secret" ? false : prop in target;
}
});Reflect forwardingInvokes default target operations inside custom proxy traps.
const p = new Proxy({ a: 1 }, {
get(target, prop, receiver) {
return Reflect.get(target, prop, receiver);
}
});Context preservationPasses receivers to Reflect to maintain correct property accessor bindings.
const target = {
_v: 10,
get v() { return this._v; }
};Execution return flagsExposes execution success values as standard true or false flags.
const obj = Object.freeze({ a: 1 });
const ok = Reflect.set(obj, "a", 2); // falseInput validationEnforces variable type constraints prior to committing assignments.
const validator = {
set(target, prop, value) {
if (typeof value !== "number") return false;
return Reflect.set(target, prop, value);
}
};Default attributesSupplies default values when missing property keys are queried.
const fallback = {
get(target, prop) {
return prop in target ? target[prop] : 0;
}
};Losing this contextAvoids method execution failure by forwarding matching receivers.
// Always pass 'receiver' to Reflect.get()Identity checksChecks references carefully since proxies do not equal target references.
const target = {};
const proxy = new Proxy(target, {});
console.log(proxy === target); // falseA Proxy wraps target objects to intercept core operations like property reads. You specify custom logic via handler functions called traps. This is useful for validation, logging, and reactivity.
A Proxy intercepts actions on objects. The Reflect API provides matching methods to execute standard behaviors. You call Reflect methods inside traps to forward requests.
Using Reflect methods correctly preserves the this binding context for get accessors. It also returns consistent booleans indicating success, avoiding silent failures in non-strict modes.
The get and set traps intercept property accesses. The has trap handles the in operator. The apply trap intercepts function executions when targets are callable.
Yes, because every trapped interaction calls a handler function. This overhead is fine for configuration boundaries or schemas. Avoid using proxies in tight, performance-critical loops.
Validation Proxy Schema
Wraps an object in a validation proxy to enforce strict data types on property assignments.
function createValidatedUser() {
const schema = {
age: "number",
name: "string"
};
return new Proxy({}, {
set(target, prop, value) {
if (prop in schema) {
if (typeof value !== schema[prop]) {
throw new TypeError(
prop + " must be a " + schema[prop]
);
}
}
return Reflect.set(target, prop, value);
}
});
}Set traps validate data before assignments commit, protecting target instances from runtime configuration bugs.