Proxy & Reflect
A Proxy wraps an object with handler traps that intercept operations like reading, writing, and checking properties, while Reflect provides matching methods to perform the default behavior — together they let you customize how objects respond to ordinary code.
Learn Proxy & Reflect in our free JavaScript course — an interactive lesson with runnable examples, a practice exercise and a quick reference.
Part of the free JavaScript course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
This is metaprogramming: the same machinery behind reactive frameworks, validation layers, and tracing tools.
📚 Prerequisites: You should be comfortable with objects and getters and setters . Proxies generalize that idea to every operation, not just one named property.
🛰️ Real-World Analogy: A Proxy is like a receptionist in front of an office :
new Proxy(target, handler) returns an object that behaves like target until one of the handler's traps fires. The get(target, key) trap runs on every property read, so you can log access or return a default for missing keys. Inside the trap, call Reflect.get to produce the normal result instead of touching target directly.
Use Reflect to forward: Reflect.get(target, key) does exactly what a plain read would, including respecting getters — safer than target[key] in edge cases.
The set(target, key, value) trap fires on every assignment. Return true to accept the write (after storing it with Reflect.set ) or throw to reject invalid data. Unlike a single setter, one trap guards all properties, so you can enforce a rule like "age must be a positive number" across the whole object.
Always return from set: the trap must return a truthy value (use Reflect.set 's result). Returning false in strict mode throws a TypeError.
The has(target, key) trap intercepts the in operator — handy for hiding "private" keys or faking membership. Combining get and set traps over an array lets you implement Python-style negative indexing, where arr[-1] means the last element. It's a classic demonstration of how proxies extend built-in behavior.
Reactivity in a nutshell: frameworks like Vue use exactly this pattern — a get trap to track which data was read and a set trap to re-run anything that depended on it.
Complete the get trap so missing keys return 0 .
Predict the output before revealing the answer.
42 — the get trap ignores the key and always returns 42.
true — Reflect.has is the function form of the in operator.
9 — Reflect.set performs the assignment and returns true.
Wrap an object so reads work but every write is silently blocked.
Up next: BigInt & Number Precision — integers beyond the safe limit. 🔢
Practice quiz
What does new Proxy(target, handler) return?
- A frozen copy of target
- A deep clone with no methods
- An object that behaves like target until a handler trap fires
- The handler object itself
Answer: An object that behaves like target until a handler trap fires. A Proxy wraps the target and behaves like it until one of the handler's traps intercepts an operation.
Which trap intercepts reading a property?
- get
- set
- has
- deleteProperty
Answer: get. The get(target, key) trap runs on every property read.
For a get trap returning Reflect.get when the key exists and "default" otherwise, what is settings.size if size is missing?
- undefined
- null
- An error
- "default"
Answer: "default". Missing keys fall through to the default, so settings.size is "default".
What is the role of the set trap?
- It reads properties
- It fires on assignment and can validate the value
- It deletes properties
- It intercepts the in operator
Answer: It fires on assignment and can validate the value. set(target, key, value) fires on every assignment, letting you validate or reject the write.
Why should a set trap return Reflect.set(...)?
- It must return a truthy value or strict mode throws
- To delete the key
- To skip the assignment
- To log the read
Answer: It must return a truthy value or strict mode throws. The set trap must return truthy; Reflect.set performs the write and returns true.
Which trap intercepts the in operator?
- get
- set
- has
- ownKeys
Answer: has. The has(target, key) trap intercepts the in operator.
Using the negative-index proxy over [10, 20, 30], what does nums[-1] return?
- 10
- 30
- undefined
- -1
Answer: 30. The get trap maps -1 to length + (-1), returning the last element, 30.
What is Reflect used for inside a trap?
- To freeze the object
- To create a new Proxy
- To throw errors automatically
- To perform the default behavior of the operation
Answer: To perform the default behavior of the operation. Reflect methods (Reflect.get, Reflect.set, etc.) perform the default operation correctly.
When checking a key in a has trap, why use String(key).startsWith("_") instead of key.startsWith("_")?
- It is faster
- Symbol keys have no startsWith method
- Strings cannot use startsWith
- key is always a number
Answer: Symbol keys have no startsWith method. Keys can be symbols, which lack startsWith; coerce with String() first.
In a read-only proxy whose set trap returns true without writing, what happens to config.retries = 99?
- It updates to 99
- It throws a TypeError
- It is silently ignored
- It deletes retries
Answer: It is silently ignored. The set trap accepts the call but never stores it, so the write is silently ignored.