What is a trap (traps)?
Traps are methods on a Proxy object
that "intercept" standard operations on an object
(reading, writing, deleting properties, calling a function, the in operator, etc.)
and let you redefine their behavior.
In other words, traps give you the ability to step into how JavaScript works and change how an object behaves.
Short version
Traps are functions defined in the second argument of Proxy -
the so-called "handler":
const proxy = new Proxy(target, handler);| Parameter | Description |
|---|---|
target | the source object (the real "target") |
handler | an object with "traps" (methods that intercept actions) |
Example - the simplest get trap
const user = { name: 'Tim' };
const proxy = new Proxy(user, {
get(target, property) {
console.log(`Reading property "${property}"`);
return target[property];
}
});
console.log(proxy.name);
// → Log: Reading property "name"
// → Output: TimHere the get trap intercepts access to the property,
and you can do whatever you want before returning the value (log, check, validate, substitute, etc.).
All the main traps
| Trap | What it intercepts | Analog |
|---|---|---|
get(target, prop, receiver) | Reading a property (obj.prop) | obj[prop] |
set(target, prop, value, receiver) | Writing a property (obj.prop = value) | obj[prop] = value |
has(target, prop) | The check prop in obj | in |
deleteProperty(target, prop) | Deletion (delete obj[prop]) | delete |
ownKeys(target) | Getting the list of keys (Object.keys, for...in) | Object.keys(obj) |
getOwnPropertyDescriptor(target, prop) | Requesting a property descriptor | Object.getOwnPropertyDescriptor() |
defineProperty(target, prop, descriptor) | Defining a new property | Object.defineProperty() |
getPrototypeOf(target) | Getting the prototype | Object.getPrototypeOf() |
setPrototypeOf(target, proto) | Changing the prototype | Object.setPrototypeOf() |
isExtensible(target) | Checking extensibility | Object.isExtensible() |
preventExtensions(target) | Preventing new properties from being added | Object.preventExtensions() |
apply(target, thisArg, args) | Calling a function | func() |
construct(target, args, newTarget) | Calling with new | new func() |
Examples of popular traps
1. set - controlling writes
const user = { name: 'Tim' };
const proxy = new Proxy(user, {
set(target, prop, value) {
if (prop === 'age' && typeof value !== 'number') {
throw new TypeError('Age must be a number!');
}
target[prop] = value;
return true; // must return true
}
});
proxy.age = 25; // ok
proxy.age = 'twenty'; // TypeError2. has - overriding the in operator
const secret = { password: '1234' };
const proxy = new Proxy(secret, {
has(target, key) {
if (key === 'password') return false;
return key in target;
}
});
console.log('password' in proxy); // falseThis way you can "hide" sensitive fields.
3. ownKeys - hiding properties during enumeration
const user = { name: 'Tim', password: '12345' };
const proxy = new Proxy(user, {
ownKeys(target) {
return Object.keys(target).filter(k => k !== 'password');
}
});
console.log(Object.keys(proxy)); // ["name"]4. apply - intercepting a function call
function sum(a, b) {
return a + b;
}
const proxy = new Proxy(sum, {
apply(target, thisArg, args) {
console.log(`Call with arguments: ${args}`);
return Reflect.apply(target, thisArg, args);
}
});
console.log(proxy(2, 3)); // "Call with arguments: 2,3" → 5The apply trap only works for functions.
5. construct - intercepting a call with new
function User(name) {
this.name = name;
}
const proxy = new Proxy(User, {
construct(target, args) {
console.log('Creating a new user...');
return new target(...args);
}
});
const tim = new proxy('Tim');
// → "Creating a new user..."How to "forward" the default behavior
To avoid breaking native behavior,
traps usually use Reflect inside them -
it performs the "real" operation under the hood.
const proxy = new Proxy(user, {
get(target, prop, receiver) {
console.log(`Reading ${prop}`);
return Reflect.get(target, prop, receiver);
}
});This guarantees that if you don't want to change the behavior - it stays "default".
Where traps are actually used
- Data validation and protection
- Access logging
- Creating "virtual" properties
- Reactive systems (Vue, MobX)
- ORM / API wrappers (for example, Prisma Proxy for models)
- Metaprogramming and test mocks
SUMMARY
| Term | What it is |
|---|---|
| Trap | A handler method on Proxy that "intercepts" an operation on an object |
| Handler | An object containing traps |
| Reflect | Used inside traps to call the default behavior |
| Target | The real object the Proxy sits over |
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.