What is a Proxy?
A Proxy wraps an object and intercepts operations on it — like reading properties, setting values, or calling functions. You define "traps" that run when these operations happen. This lets you add custom behavior to any object.
const user = { name: "Alice", age: 25 };
const proxy = new Proxy(user, {
get(target, prop) {
console.log(`Reading "${prop}"`);
return target[prop];
},
set(target, prop, value) {
console.log(`Setting "${prop}" to ${value}`);
target[prop] = value;
return true;
},
});
proxy.name; // Logs: Reading "name"
proxy.age = 26; // Logs: Setting "age" to 26
Common Traps
There are 13 different traps you can define. The most commonly used ones are get, set, has, and deleteProperty.
const handler = {
get(target, prop, receiver) {}, // Intercept property reads
set(target, prop, value, receiver) {}, // Intercept property writes
has(target, prop) {}, // Intercept 'in' operator
deleteProperty(target, prop) {}, // Intercept delete
apply(target, thisArg, args) {}, // Intercept function calls
construct(target, args) {}, // Intercept new operator
};
Practical Example: Validation
Proxies are great for data validation. You can prevent invalid values from being set on an object.
function createValidatedUser(data) {
return new Proxy(data, {
set(target, prop, value) {
if (prop === "age" && (typeof value !== "number" || value < 0)) {
throw new Error("Age must be a positive number");
}
if (prop === "email" && !value.includes("@")) {
throw new Error("Invalid email");
}
target[prop] = value;
return true;
},
});
}
const user = createValidatedUser({ name: "Alice", age: 25 });
user.age = 30; // OK
user.age = -5; // ❌ Error: Age must be a positive number
Try it Yourself →
Reactive Data with Proxies
Frameworks like Vue 3 use proxies under the hood to make data reactive. When you change a property, the proxy notifies any watchers to update the UI.
function reactive(obj, onUpdate) {
return new Proxy(obj, {
set(target, prop, value) {
target[prop] = value;
onUpdate(prop, value);
return true;
},
});
}
const state = reactive({ count: 0 }, (prop, value) => {
console.log(`${prop} changed to ${value}`);
document.querySelector("#count").textContent = value;
});
state.count = 1; // Logs: count changed to 1
Summary
Proxies intercept and customize operations on objects. Use them for validation, logging, reactive data, and access control. They're a powerful metaprogramming tool in JavaScript.