Proxies & Reflect
Intercepting the Language Itself
Every time JavaScript reads a property, it performs an internal operation called [[Get]]. Every assignment performs [[Set]]. Every new call performs [[Construct]]. These operations happen silently, always, for every object.
A Proxy lets you intercept these operations and run your own code instead — or in addition. You wrap any object in a Proxy, define traps for whichever operations you care about, and the Proxy calls your trap whenever that operation is triggered.
Start by seeing the simplest possible Proxy — one that logs every property access:
new Proxy(target, handler) takes two arguments: the object to wrap, and a handler object whose methods are the traps. The original student object is untouched — the Proxy sits in front of it and intercepts.
The get and set Traps
The two most useful traps. get intercepts reads, set intercepts writes:
The Proxy turned a plain object into a self-validating record. No class, no setter methods — just a Proxy wrapping an empty object and enforcing rules on every write.
The has Trap — Intercepting in
The in operator now reads as natural English: 15 in teens. The underlying object has no numeric keys at all — the trap synthesised the answer from the start and end values.
The apply Trap — Intercepting Function Calls
Proxies work on functions too. The apply trap intercepts every call:
Notice Reflect.apply — we will cover Reflect properly shortly. It calls the original function cleanly from inside a Proxy trap.
The construct Trap — Intercepting new
Reflect — The Clean Way to Call Default Behaviour
Reflect is an object with one static method for each Proxy trap — Reflect.get, Reflect.set, Reflect.has, Reflect.apply, and so on. Each method performs the default JavaScript operation.
Why use Reflect instead of doing it manually inside a trap?
Reflect mirrors the Proxy trap API exactly — same names, same arguments in the same order. Trap intercepts the operation; Reflect performs it. The pattern is always: intercept → do your extra work → delegate to Reflect.
A Reactive Object — How Vue and MobX Work
The set trap is how reactive frameworks detect state changes and trigger re-renders. Here is the mechanism stripped to its core:
Every assignment to state triggers the onChange callback — which in Vue or MobX re-renders the component that depends on that value. The component author writes state.marks = 82 and the UI updates. The Proxy is the entire mechanism.
Revocable Proxies — Proxies You Can Switch Off
Proxy.revocable creates a Proxy that can be permanently disabled:
All Available Traps
A Proxy can intercept 13 operations in total. The ones you will reach for most:
| Trap | Triggered by |
|---|---|
get | obj.prop, obj[key] |
set | obj.prop = val |
has | key in obj |
deleteProperty | delete obj.prop |
apply | fn(), fn.call(), fn.apply() |
construct | new Cls() |
ownKeys | Object.keys(), for...in |
getPrototypeOf | Object.getPrototypeOf(), instanceof |
What You Have Learned
Proxies are metaprogramming — writing code that controls how other code behaves at the language operation level.
The key ideas:
new Proxy(target, handler)wraps any object or function; handler methods are trapsgetandsettraps turn plain objects into validated, reactive, or logged data storeshastrap customises theinoperator — range checks, membership testsapplytrap intercepts function calls — memoization, logging, rate-limitingconstructtrap interceptsnew— singletons, instance counts, factoriesReflectmirrors every trap with the default behaviour — always preferReflect.get(target, key, receiver)overtarget[key]inside a trapProxy.revocablecreates proxies you can permanently disable — useful for capability-based access control- Vue 3's reactivity, MobX's observables, and most validation libraries are built on exactly this mechanism
Next lesson is where we move into advanced territory: Performance & the JavaScript Engine — how V8 compiles your code, what hidden classes are, why certain patterns are dramatically faster than others, and how to write JavaScript that the engine can optimise. You do not need to create the advanced folder yet — I will tell you at the start of that lesson.