Mastering JavaScript Proxy: Enhance Object Behavior with Dynamic Interception

Learn how to use JavaScript Proxy to dynamically intercept and customize object behavior for enhanced flexibility and control, with beginner-friendly examples.

JavaScript Proxy is a powerful feature that allows you to intercept and customize operations performed on objects, such as property access, assignment, and function calls. It acts as a wrapper around an object and lets you define custom behaviors dynamically, making your code more flexible and robust.

In this tutorial, we'll explore the basics of JavaScript Proxy, see how to create a proxy, and learn common use cases where Proxy can enhance the behavior of your objects.

### What is a Proxy in JavaScript?

A Proxy takes two arguments: a target object (the original object you want to wrap) and a handler object. The handler defines traps - functions that intercept operations like getting or setting a property.

javascript
const target = { greeting: 'hello' };

const handler = {
  get: (obj, prop) => {
    console.log(`Property '${prop}' was accessed.`);
    return obj[prop];
  },
};

const proxy = new Proxy(target, handler);

console.log(proxy.greeting);  // Output: hello
// Also logs: Property 'greeting' was accessed.

In the example above, we created a proxy to intercept the `get` operation. Whenever a property is accessed on `proxy`, the handler's `get` trap runs, logging access calls.

### Common Traps in Proxy

Some popular traps you can define include: - `get`: intercepts property access - `set`: intercepts property assignment - `deleteProperty`: intercepts deletion of a property - `has`: intercepts the `in` operator - `apply`: intercepts function calls - `construct`: intercepts constructor calls

### Example: Validating Property Values

Let's use Proxy to validate property values before setting them:

javascript
const user = {
  name: 'Alice',
  age: 25
};

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

const proxyUser = new Proxy(user, validator);

proxyUser.age = 30;      // Works fine
//proxyUser.age = -5;   // Throws error: Age must be a positive number
//proxyUser.age = 'old'; // Throws error

In this example, when we try to set the `age` property, our proxy validates that the value is a positive number. If not, it throws an error, thereby protecting the object from invalid data.

### Example: Logging Property Deletion

You can also monitor when properties get deleted:

javascript
const obj = { prop1: 1, prop2: 2 };

const handler = {
  deleteProperty(target, prop) {
    console.log(`Deleting property: ${prop}`);
    return delete target[prop];
  }
};

const proxy = new Proxy(obj, handler);

delete proxy.prop1;  // Logs: Deleting property: prop1
console.log(proxy.prop1); // undefined

### When to Use Proxy?

Use Proxy when you need dynamic behavior such as validation, logging, auto-populating properties, or restricting object property access. It can simplify code that previously required verbose getter/setter methods.

### Summary

JavaScript Proxy is a versatile tool to intercept and customize object operations dynamically. By mastering its traps, you can add powerful features like validation, logging, and more with just a small layer of code wrapping your objects. Start experimenting with Proxy to unlock new patterns in your JavaScript programming!