JavaScript Proxy and it's use cases

JavaScript

The Proxy is a standard built-in object introduced in ES6. It acts as a gatekeeper for an object.

It's a wrapper around an object that can be used to modify fundamental operations like getting, setting of the original object.

const proxy = new Proxy(targetObject, handler);

targetObject → The object that we are wrapping with the proxy.
handler → An object that defines which operations will be modified

Example

const handler = {
  get(target, prop) {
    console.log(`Getting ${prop}: `);
    return target[prop];
  },
  set(target, prop, value) {
    console.log(`Setting ${prop} to ${value}`);
    target[prop] = value;
    return true;  // Required for "set" to work
  }
};

const person = { name: "Riya", email: "hello@fariabriya.codes" };

const proxyPerson = new Proxy(person, handler);

console.log(proxyPerson.name);
// Getting name
// Riya
proxyPerson.profession = "Software Engineer"
// Setting profession to Software Engineer

Here are some examples of what we can do with Proxies-

1.Making an object Immutable

const handler = {
  set(target, prop, value) {
    throw new Error(`Modification of key is not allowed`)  
    return false; // Prevent the assignment
  },
};

2.Handle Negative index and out of range

const arrayHandler = {
  get(target, prop) {
    const index = Number(prop);
    if (index < 0 || index >= target.length) {
      throw new Error(`Index ${index} is out of bounds`);
    }
    return target[prop]; // Return the actual value if valid
  },
  set(target, prop, value) {
    const index = Number(prop);
    if (index < 0) {
      throw new Error(`Cannot set value at negative index ${index}`);
    }
    target[prop] = value; // Set value if valid
    return true; // Indicate success
  }
}

3.Applying multiple operations

function mathBuilder(value = 0) {
  return new Proxy(() => value, {
    get(target, prop) {
      return (num) => mathBuilder(eval(`${value} ${prop} ${num}`));
    },
    apply(target, thisArg, args) {
      return value; // Evaluate final result when called
    }
  });
}
// Usage
const calc = mathBuilder(10);

const result = calc.plus(5).times(2).minus(3)();
console.log(result); // Output: 24

4.Adding validation on specific keys

const handler = {
  set(target, prop, value) {
    if (prop === 'amount' && value < 0) {
      throw new Error(`Amount cannot be negative`)
    }
    target[prop] = value;
    return true;
  },
  get(target, prop) {
    return target[prop]
  }
};
const product = new Proxy({name : 'Apple', amount: 12 }, handler)
product.amount = -2 // Error: Amount cannot be negative