Proxy is JavaScript's metaprogramming primitive. At Google, we use it for validation layers, reactive systems, and API mocking.
What is a Proxy?
A Proxy wraps an object and intercepts operations like property access, assignment, deletion, and function calls.
const handler = {
get(target, prop, receiver) {
console.log(`Accessing ${prop}`);
return Reflect.get(target, prop, receiver);
},
set(target, prop, value, receiver) {
console.log(`Setting ${prop} = ${value}`);
return Reflect.set(target, prop, value, receiver);
}
};
const user = new Proxy({}, handler);
user.name = "Rahul"; // logs: Setting name = Rahul
console.log(user.name); // logs: Accessing nameWhy Reflect?
Reflect provides the default behavior for each trap. Always use Reflect inside proxy traps to maintain correct behavior with inheritance and receivers.
Practical Patterns
1. Validation Layer
const validated = new Proxy({}, {
set(target, prop, value) {
if (prop === "age" && (typeof value !== "number" || value < 0)) {
throw new TypeError("Age must be a positive number");
}
return Reflect.set(target, prop, value);
}
});2. Negative Array Indexing
function negativeArray(arr) {
return new Proxy(arr, {
get(target, prop) {
const index = Number(prop);
if (index < 0) return target[target.length + index];
return Reflect.get(target, prop);
}
});
}
const arr = negativeArray([1, 2, 3]);
arr[-1]; // 33. Observable Objects (Vue 3 Reactivity)
Vue 3's reactivity system is built entirely on Proxy. Every reactive object is a Proxy that tracks which properties are accessed during rendering and triggers re-renders on changes.
Performance Considerations
Proxies add overhead to every operation. Don't use them in hot paths. At Google, we use Proxies in development (for validation/debugging) and strip them in production builds.