Suggest an editImprove this articleRefine the answer for “What is a trap (traps)?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**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 let you step into how JavaScript works and change how an object behaves. **Key point:** traps are defined in the second argument of `Proxy` - the so-called "handler".Shown above the full answer for quick recall.Answer (EN)Image**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"**: ```javascript 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 ```javascript 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: Tim ``` Here 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 ```javascript 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'; // TypeError ``` --- ### 2. `has` - overriding the `in` operator ```javascript 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); // false ``` This way you can "hide" sensitive fields. --- ### 3. `ownKeys` - hiding properties during enumeration ```javascript 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 ```javascript 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" → 5 ``` The `apply` trap only works for **functions**. --- ### 5. `construct` - intercepting a call with `new` ```javascript 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. ```javascript 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 |For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.