DEV Community

Julio Leiva Díaz
Julio Leiva Díaz

Posted on

Proxy Pattern easy and practice

A proxy object can determine the behavior whenever we’re interacting with the object, for example when we’re getting a value, or setting a value.

We have an account object, that represents my data account:

const account = {
  name: "Julio",
  isPremium:false,
  isLogged: true
}
Enter fullscreen mode Exit fullscreen mode

A user should not be able to change the login properties or the service type or assign empty values to any of the properties. We also have to check if the user is trying to access a property of the object that does not exist, and if so, inform the user about it. And it is here where it makes sense to use a proxy, which is basically a second object that is responsible for “monitoring” the interactions that are made on the original object. Something like a soccer player’s agent or a management secretary.

Instead of interacting with this object directly (soccer player or CEO) , we want to interact with a proxy object. In JavaScript, we can easily create a new proxy by creating a new instance of Proxy.

const accountProxy = new Proxy(account, {});
Enter fullscreen mode Exit fullscreen mode

The second argument of Proxy is an object that represents the handler. In the handler object, we can define specific behavior based on the type of interaction. Although there are many methods that you can add to the Proxy handler, the two most common ones are get and set:

get: invoked when trying to access a property
set: invoked when trying to modify a property

Instead of interacting with the account object directly, we are going to interact with the accountProxy.

We add two handlers to the accountProxy accountProxy. The first one, the setter, will act when we try to modify a property. By invoking the set method on the Proxy, we want the proxy to register the previous value and the new value of the property. The second, the getter, will come into action when a property is accessed. When invoking the get method on the Proxy, we want the proxy to register the key and the value of the property and inform us of this through a log.

const accountProxy = new Proxy(account, {
  get: (obj, prop) => {
    console.log(`The value of ${prop} is ${obj[prop]}`);
  },
  set: (obj, prop, value) => {
    console.log(`Changed ${prop} from ${obj[prop]} to ${value}`);
    obj[prop] = value;
  }
});
accountProxy.name // The value of name is Julio
accountProxy.isPremium = true // Changed isPremium from false to true
Enter fullscreen mode Exit fullscreen mode

As we have mentioned before, by using our Proxy we want to:

user should not be able to change the login properties or the service type
or assign empty values to any of the properties
and check if the user is trying to access a property of the object that does not exist, and if so, inform the user about it

const account = {
  name: "Julio",
  isPremium:false,
  isLogged:true
}
const accountProxy = new Proxy(account, {
  get: (obj, prop) => {
    if (!obj[prop]) {
      console.log(
        `This property doesn't exist on the target object`
      );
    } else {
      console.log(`The value of ${prop} is ${obj[prop]}`);
    }
  },
  set: (obj, prop, value) => {
    if (prop === "name" && typeof value !== "string") {
      console.log(`You can only pass string values for name property.`);
    } else if (prop === "name" && !value.length) {
      console.log(`You need to provide a valid name.`);
    } else if(prop === "isPremium"  && typeof value === "boolean"){
      console.log(`You can't modify ${prop} from ${obj[prop]}`);
    }
    else if(prop === "isLogged"  && typeof value === "boolean"  ){
      console.log(`You can't modify ${prop} from ${obj[prop]}`);
    }
  }
});
accountProxy.name= "" // You need to provide a valid name
accountProxy.noExistProp // This property doesn't exist on the target object
accountProxy.isPremium = true // You can't modify isPremium from false
Enter fullscreen mode Exit fullscreen mode

Proxies are a powerful way to add control over the behavior of an object. A proxy can have various use-cases: it can help with validation, formatting, notifications, or debugging.

Overusing the Proxy object or performing heavy operations on each handler method invocation can easily affect the performance of your application negatively. It's best to not use proxies for performance-critical code.

Check here, in this free video from Vue Mastery (with Evan You and Gregg Pollack) how Vue 3 implements the Proxy pattern to create its reactivity system. It’s wonderful 👌

I hope you found this article useful.

Top comments (0)