This chapter follows QuickTip: Freezing and sealing objects.
Proxy lets you define a handler with traps that run when code interacts with a target object. Frameworks use proxies for reactivity (Vue 3, some state libraries) and for defensive wrappers around untrusted data.
Basic get and set traps
const target = { count: 0 };
const observed = new Proxy(target, { get(obj, prop, receiver) { return Reflect.get(obj, prop, receiver); }, set(obj, prop, value, receiver) { console.log('set', prop, value); return Reflect.set(obj, prop, value, receiver); },});
observed.count = 1;Traps must preserve invariants for non-configurable properties and Array length; violating them throws TypeError.
Reflect
Reflect provides the same operations as the language builtins (Reflect.get, Reflect.set, Reflect.has, Reflect.defineProperty, …) with a uniform return style—especially Reflect.set returning a boolean instead of throwing in some edge cases.
Using Reflect.* inside traps forwards default behavior and keeps receiver correct for getters that depend on this.
Common use cases
- Validation: reject invalid assignments in a
settrap. - Defaults: return a stand-in from
getwhen the key is missing. - Revocable proxies:
Proxy.revocablereturns{ proxy, revoke }to cut off access later—handy for capability security patterns.
Proxies add overhead; use them at boundaries (API clients, state trees), not on every plain object in a hot loop.
That completes the Objects and Classes series. For how functions close over object state, see Scope and closures.