InterviewHubPRO
Section Overview
Q511

Question 511 of 521

Part 8: Modern JavaScript APIs, WeakRef, Proxy & Performance (464 - 521)

98%
JavaScript Internals (521 Qs)•Part 8: Modern JavaScript APIs, WeakRef, Proxy & Performance (464 - 521)

What are Proxy traps and what operations can they intercept?

Proxy traps are handler methods that intercept fundamental operations on objects, allowing you to customize their behavior.

Available traps:

javascript
 const handler = {
   // Property access
   get(target, prop, receiver) {
     console.log(`Getting ${prop}`);
     return Reflect.get(target, prop, receiver);
   },

   // Property assignment
   set(target, prop, value, receiver) {
     console.log(`Setting ${prop} to ${value}`);
     return Reflect.set(target, prop, value, receiver);
   },

   // Property deletion
   deleteProperty(target, prop) {
     console.log(`Deleting ${prop}`);
     return Reflect.deleteProperty(target, prop);
   },

   // 'in' operator
   has(target, prop) {
     console.log(`Checking ${prop}`);
     return Reflect.has(target, prop);
   },

   // Object.keys, for...in
   ownKeys(target) {
     return Reflect.ownKeys(target);
   },

   // Function calls
   apply(target, thisArg, args) {
     console.log(`Called with ${args}`);
     return Reflect.apply(target, thisArg, args);
   },

   // new operator
   construct(target, args) {
     console.log(`Constructed with ${args}`);
     return Reflect.construct(target, args);
   },

   // Object.getPrototypeOf
   getPrototypeOf(target) {
     return Reflect.getPrototypeOf(target);
   },

   // Object.setPrototypeOf
   setPrototypeOf(target, proto) {
     return Reflect.setPrototypeOf(target, proto);
   },

   // Object.isExtensible
   isExtensible(target) {
     return Reflect.isExtensible(target);
   },

   // Object.preventExtensions
   preventExtensions(target) {
     return Reflect.preventExtensions(target);
   },

   // Object.getOwnPropertyDescriptor
   getOwnPropertyDescriptor(target, prop) {
     return Reflect.getOwnPropertyDescriptor(target, prop);
   },

   // Object.defineProperty
   defineProperty(target, prop, descriptor) {
     return Reflect.defineProperty(target, prop, descriptor);
   }
 };

Validation example:

javascript
 const validator = {
   set(target, prop, value) {
     if (prop === 'age') {
       if (typeof value !== 'number' || value < 0) {
         throw new TypeError('Age must be a positive number');
       }
     }
     target[prop] = value;
     return true;
   }
 };

 const person = new Proxy({}, validator);
 person.age = 30; // OK
 // person.age = -5; // Throws error

Property access logging:

javascript
 function createLoggingProxy(obj, name = 'object') {
   return new Proxy(obj, {
     get(target, prop) {
       console.log(`${name}.${String(prop)} accessed`);
       const value = target[prop];
       if (typeof value === 'object' && value !== null) {
         return createLoggingProxy(value, `${name}.${String(prop)}`);
       }
       return value;
     }
   });
 }

 const user = createLoggingProxy({ name: 'John', address: { city: 'NYC' } });
 user.address.city; // Logs: object.address accessed, object.address.city accessed

Negative array indices:

javascript
 function createArray(arr) {
   return new Proxy(arr, {
     get(target, prop) {
       const index = Number(prop);
       if (index < 0) {
         return target[target.length + index];
       }
       return target[prop];
     }
   });
 }

 const arr = createArray([1, 2, 3, 4, 5]);
 console.log(arr[-1]); // 5
 console.log(arr[-2]); // 4

Function argument validation:

javascript
 function validateArgs(fn, validators) {
   return new Proxy(fn, {
     apply(target, thisArg, args) {
       validators.forEach((validator, i) => {
         if (!validator(args[i])) {
           throw new Error(`Invalid argument at position ${i}`);
         }
       });
       return Reflect.apply(target, thisArg, args);
     }
   });
 }

 const add = validateArgs(
   (a, b) => a + b,
   [
     x => typeof x === 'number',
     x => typeof x === 'number'
   ]
 );

 console.log(add(1, 2)); // 3
 // add('1', 2); // Throws error