If you’ve ever wanted to validate object properties automatically,
track changes reactively, or build a mock API client that feels real — the
Proxy object is your tool. Yet somehow it flies under the radar
for most developers.
Introduced in ES2015, Proxy wraps an object and lets you intercept
fundamental operations — property reads, writes, deletions, and more — via
“traps” defined on a handler object.
The anatomy of a Proxy
A Proxy takes two arguments: the target (the object being wrapped) and the handler (an object defining which operations to intercept). Every interceptable operation has a corresponding trap method on the handler.
const handler = {
get(target, key) {
return key in target
? target[key]
: `Property "${key}" doesn’t exist`
},
set(target, key, value) {
if (typeof value !== 'number') {
throw new TypeError('Only numbers allowed')
}
target[key] = value
return true
}
}
const proxy = new Proxy({}, handler)
proxy.score = 42 // ✓ works
proxy.score = 'oops' // ✗ TypeError
The get trap runs on every property access. The set trap
intercepts every assignment. Return true from set to signal
success — otherwise you’ll get a TypeError in strict mode.
Real-world use cases
The real power isn’t abstract. Proxy unlocks patterns that are otherwise painful or impossible.
“A Proxy doesn’t change what your object is — it changes what your object does when the runtime touches it.”
Reactive state
Vue 3’s reactivity system is built entirely on Proxy. When you access a reactive
property, Vue’s get trap tracks the dependency. When you mutate it,
the set trap schedules re-renders. No syntax overhead. Just assignment.
Input validation
Instead of scattering guard clauses through your codebase, centralise validation in a Proxy handler. The contract lives in one place. Every consumer benefits automatically.
API mocking
Wrap a plain object in a Proxy that intercepts property access and returns async functions. You get a fully-typed mock client that mirrors your real API surface — without any code generation.
Performance considerations
Proxies are not free. Every trap fires a function call. In tight loops over large collections, this adds up. Benchmark before you commit. For most use cases — form state, reactive stores, config validation — the overhead is completely negligible.
The V8 team has steadily optimised Proxy performance since ES2015. Don’t avoid Proxy out of dated fear — measure it first.