How to Use Proxy Objects in JavaScript

ยท

4 min read

How to Use Proxy Objects in JavaScript

Objects in JavaScript are useful data types that let us define complex data with simple key-value pairs, like a dictionary. Sometimes, you might want to change how JavaScript objects work by default. This is where Proxy Objects are helpful. In this article, we will discuss what proxy objects are, why they are useful, and how to use them.

What is a Proxy Object?

Before understanding what a Proxy Object is, let's look at the word Proxy. A proxy means something that acts like the original thing but isn't the original thing. Similarly, a Proxy Object is an object created using the original object that can intercept and change how the original object works.

The Proxy constructor takes two parameters

  • target: the object you want to create a proxy for

  • handler: an object with operations you want to change or redefine

const proxyObject = new Proxy(target, handler)

How Does a Proxy Object Work?

When we create Proxy Objects with a handler that has operations you want to change, it intercepts those operations, catches the call to the target object, and runs the custom logic you defined for those operations.

The operations are called traps, which are basically the internal methods of an object. Some of them are:

  • get

  • set

  • deleteProperty

Here, I have created a simple visual showing how a Proxy Object works. If we try to access or set a value, it intercepts and runs the operations (traps) defined in the handler.

Alright, I hope the what and how of Proxy Objects are clear. Next, we will discuss some use cases to show why Proxy Objects are useful.

Use cases of Proxy Object

Logging

Let's say you want to create a system where every time a property is accessed from the object, it logs the information.

const platform = {
  type: "peerlist.io",
  handle: "sachin87",
};

const proxyPlatformObj = new Proxy(platform, {
  get(target, key) {
    console.log(`[Info]: Accessing ${key} at ${Date.now()}`);
    return target[key];
  },
});

// try to access the property
proxyPlatformObj.type;

// [Info]: Accessing type at 1729661722827

// 'peerlist.io'

This is a very simple use case, but it's useful when logging is needed, and you can expand it to do more advanced things.

We can also let users access properties that aren't directly available. For example, in the case above, we might want the full URL of the platform with the user handle.

const proxyPlatformObj = new Proxy(platform, {
  get(target, key) {
    console.log(`[Info]: Accessing ${key} at ${Date.now()}`);
    if (key === "url") {
      return `https://${target.type}/${target.handle}`;
    }
    return target[key];
  },
});

// try to access the url property
proxyPlatformObj.url;

// [Info]: Accessing url at 1729662118855
// 'https://peerlist.io/sachin87'

Validation

Another use case is checking the value before adding it. For instance, let's say we want to check the handle's value before setting it. We will validate two basic conditions:

  • It should be in lowercase

  • It can be alphanumeric

const proxyPlatformObj = new Proxy(platform, {
  set(target, key, value) {
    if (key === "handle" && !(/^[a-z0-9]+$/.test(value))) {
      console.error(`[Error]: ${key} should be in small case and can be alphanumerical`);
    } else {
      return Reflect.set(target, key, value);
    }
  },
});

proxyPlatformObj.handle="Sachin87"
// [Error]: handle should be in small case and can be alphanumerical

You might be wondering what Reflect.set(target, key, value) is. It's a namespace object with static methods for calling JavaScript object's internal methods that can be intercepted. If you don't want validation for all properties, you can use the Reflect object to keep the default behavior.

We talked about two use cases logging and validation, but you can intercept other internal methods based on your needs.

Conclusion

We talked about what a Proxy Object is, how it works, and some of its uses. A Proxy Object is helpful, but we should be aware of its downsides. We should use it only when necessary to avoid adding complexity or bugs by mistake.

That's all for this topic. Thank you for reading! If you found this article helpful, please consider liking, commenting, and sharing it with others.

Further Reading

Did you find this article valuable?

Support Sachin Chaurasiya Blogs by becoming a sponsor. Any amount is appreciated!

ย