A Proxy in JavaScript is an object that allows you to intercept and redefine the default behavior of fundamental operations (like property access, assignment, function calls, etc.) on another object (called the target). Proxies were introduced in ES6 and are created using the Proxy constructor.  This can be useful for a variety of purposes, such as logging, validation, access control and caching. In this article, we will show you Proxy in JavaScript and use cases.

Syntax of Proxy:

const proxy = new Proxy(target, handler);

target:     The object you want to proxy (can be any object, including functions).

handler:  An object that defines the custom behavior for the proxy. It contains trap functions (methods that intercept operations).

Use Cases of Proxy:

Validation using Proxy:

In this example, we’ll create a proxy for an object that validates the data being passed to it:

// This is the interface we want to restrict the data to
const employeeDetail = {
  fullName: '',
  age: 0,
};

// This is the validator which will be used by the Proxy
const modelValidator = {
  set(target, prop, value) {
    if (prop === 'age' && typeof value !== 'number') {
      throw new TypeError('Age must be a number');
    }
    if (prop === 'fullName' && typeof value !== 'string') {
      throw new TypeError('Full name must be a string');
    }

    if (!Object.keys(target).includes(prop)) {
       throw new TypeError('You cannot set anything else other than age and full name');
    }
    return Reflect.set(target, prop, value);
  },
};


If we attempt to instantiate a new object and try to set a property that does not conform to the model, an error will be thrown. For example, we cannot set the gender property on the useEmployyDetail object. Additionally, note that we have two more validation cases for the value types of age and fullName.

const useEmployyDetail = new Proxy(employeeDetail, modelValidator);

useEmployyDetail.fullName = 'Sagar Nakrani';
useEmployyDetail.age = 25;
userDanuseEmployyDetailiel.gender = "male";

// Output: TypeError: You cannot set anything else other than age and full name

Access control with Proxy:

In this example, we create a proxy for an object that restricts access to specific properties

const secretData = {
  secret: 'This is super secret',
  public: 'This is public stuff',
  misc: 'Other stuff'
};

const handler = {
  get(target, prop, receiver) {
    if (prop === 'secret') {
      throw new Error('Access denied');
    }
    return Reflect.get(target, prop, receiver);
  },
};

const data = new Proxy(secretData, handler);

console.log(data.public);
// Output: This is public stuff
console.log(data.secret);
// Output: Error: Access denied

As you can see, the proxy blocks access to the secret property and throws an error if an attempt is made to access it.

Caching with Proxy:

In this code snippet, we’ll create a proxy for a function that caches its results so we also can achieve caching using a proxy.

function muliplyOperation(n) {
  console.log(`Performing multiply operation for ${n}`);
  return n * n;
}

const cache = new Map();

const handler = {
  apply(target, thisArg, args) {

    const key = args[0];

    if (cache.has(key)) {
      console.log(`Returning cached result for ${key}`);
      return cache.get(key);
    }
    const result = Reflect.apply(target, thisArg, args);
    cache.set(key, result);
    return result;
  },
};

const calculate = new Proxy(expensiveOperation, handler);

console.log(calculate(200));
// Output: Performing multiply operation for 200, 40000

console.log(calculate(200));
// Output: Performing multiply operation for 200, 40000

In this example, we create a proxy for a function that performs an mutiplication operation. A caching mechanism is added to the apply handler, which checks if the result of the operation is already cached. If it is, the proxy returns the cached result instead of repeating the operation.

Data Binding / Observables:

React to changes in an object’s properties (used in frameworks like Vue.js).

const handler = {
    set: (target, property, value) => {
        console.log(`Property ${property} set to ${value}`);
        target[property] = value;
        return true;
    }
};
const data = {};
const proxy = new Proxy(data, handler);
proxy.name = 'Alice'; // Logs: Property name set to Alice

Default Values:

Provide default values for undefined properties.

const handler = {
    get: (target, property) => {
        return property in target ? target[property] : 'Default Value';
    }
};
const obj = { name: 'John' };
const proxy = new Proxy(obj, handler);
console.log(proxy.name);  // John
console.log(proxy.age);   // Default Value

Conclusion:

JavaScript Proxy is a powerful feature that provides a flexible way to control and extend the behavior of objects. With the ability to intercept and redefine fundamental operations, proxies open up a wide range of possibilities for validation, security, data binding, and more.

You may also like this:

A Comprehensive Guide to Recursion with JavaScript

Rate this post

Categorized in: