The JavaScript Proxy object
A Proxy wraps an object and lets you intercept fundamental operations on it — reading a property, writing one, checking existence — through a handler of trap functions. new Proxy(target, handler). It's used for validation, logging, default values and reactivity (it's how Vue 3's reactivity works).
Overview
A Proxy sits in front of an object (the target) and intercepts operations performed on it. You provide a handler object whose methods — called traps — run instead of the default behavior. The most common traps are get (reading a property) and set (writing one), but there are traps for has (the in operator), deleteProperty, function calls and more.
This opens up patterns that are otherwise awkward. A set trap can validate assignments (reject a negative age, enforce a type). A get trap can supply default values for missing properties, log every access, or compute values on the fly. The most famous real-world use is reactivity: frameworks like Vue 3 wrap your data in a Proxy so they can detect reads and writes and update the UI automatically.
Proxies are typically paired with Reflect, which provides default implementations of each operation — inside a trap you call Reflect.get(target, prop) to do the normal thing after your custom logic. They're a powerful, advanced tool: there's a small performance cost and they can make code harder to follow, so reach for them when interception genuinely simplifies the problem (validation layers, reactive state, API mocking), not for everyday objects.
Syntax
const proxy = new Proxy(target, handler);
const handler = {
get(target, prop) { return prop in target ? target[prop] : "N/A"; },
set(target, prop, value) {
if (prop === "age" && value < 0) throw new Error("invalid");
target[prop] = value;
return true;
}
};
Example
<pre id="out" style="font:14px ui-monospace,monospace"></pre>
<script>
const safe = new Proxy({}, {
get(target, prop) { return prop in target ? target[prop] : 'unknown'; },
set(target, prop, value) {
if (prop === 'age' && value < 0) return false;
target[prop] = value; return true;
}
});
safe.name = 'Ada';
document.getElementById('out').textContent =
'name: ' + safe.name + '\n' +
'missing: ' + safe.email; // name: Ada / missing: unknown
</script>
Best practices
- Use a
Proxyfor validation, default values, logging or reactive state — not for ordinary objects. - Pair traps with Reflect to perform the default operation cleanly.
- Return
truefrom asettrap to indicate success (or it throws in strict mode). - Be mindful of the performance cost and added indirection — keep handlers simple.
Frequently asked questions
What is a Proxy in JavaScript?
What are Proxies used for?
What is the difference between Proxy and Reflect?
Proxy intercepts operations; Reflect provides the default implementations of those operations, which you call inside traps.