patternjavascriptModerate
Proxy and Reflect for meta-programming and observable objects
Viewed 0 times
ES2015
ProxyReflectmeta-programmingobservablereactivevalidation proxy
Problem
You need to intercept property access, assignment, or deletion on an object for validation, logging, reactivity (like Vue 3), or virtualisation of remote data.
Solution
Proxy wraps an object and intercepts operations via handler traps. Reflect provides the default implementations.
function createValidator(target, schema) {
return new Proxy(target, {
set(obj, prop, value) {
if (schema[prop] && !schemaprop) {
throw new TypeError(
}
return Reflect.set(obj, prop, value);
},
});
}
function createValidator(target, schema) {
return new Proxy(target, {
set(obj, prop, value) {
if (schema[prop] && !schemaprop) {
throw new TypeError(
Invalid value for ${prop});}
return Reflect.set(obj, prop, value);
},
});
}
Why
Proxy intercepts at the language level — consumer code is unmodified. Reflect.set correctly handles inherited setters and returns the boolean success flag that set traps must return.
Gotchas
- Always use Reflect.* inside traps to forward default behaviour — raw operations can bypass invariant checks
- Proxy cannot intercept Object.getOwnPropertyDescriptor without the matching trap
- Proxied class instances may break instanceof checks
- Performance overhead — avoid Proxy in hot paths with millions of operations per second
Code Snippets
Observable object with Proxy and Reflect
function observable(obj) {
return new Proxy(obj, {
set(target, prop, value, receiver) {
console.log(`${prop} changed: ${target[prop]} -> ${value}`);
return Reflect.set(target, prop, value, receiver);
},
deleteProperty(target, prop) {
console.log(`${prop} deleted`);
return Reflect.deleteProperty(target, prop);
},
});
}
const state = observable({ count: 0 });
state.count = 1; // logs: count changed: 0 -> 1Revisions (0)
No revisions yet.