JavaScript Proxy

Learn via video course
FREE
View all courses
JavaScript Course With Certification: Unlocking the Power of JavaScript
JavaScript Course With Certification: Unlocking the Power of JavaScript
by Mrinal Bhattacharya
84785
4.8
Start Learning
JavaScript Course With Certification: Unlocking the Power of JavaScript
JavaScript Course With Certification: Unlocking the Power of JavaScript
by Mrinal Bhattacharya
84785
4.8
Start Learning
Topics Covered

Overview

In this article, we will go through the concept of proxies in Javascript, where and how they are used, the various methods to use Javascript proxy, and finally their advantages and disadvantages.

Introduction to Javascript Proxy

Have you ever felt the need to get more control over how the properties or values of an object or an array are being manipulated or handled? Maybe it is required that only certain data types are allowed for a property, or the data needs to be validated before storing it in the object. All this can be accomplished with the help of a Javascript Proxy Object.

In general, proxy refers to a person who is authorized to perform some particular actions on the behalf of some other person.

Javascript Proxy is a special object that does the same job as described above: it allows us to replace the original object by creating another object that can be used in its place and may intercept or redefine (or customise) some fundamental Object operations of reading, writing or handling properties.

In other words, with Proxy Object you can build an object with functionality that gives you command over common operations that take place when utilising an object.

Hence, a proxy object provides more power and flexibility over how can the original object be interacted with. Common uses for proxy objects include logging property accesses and validating, formatting, or sanitizing inputs. A proxy object is said to 'wrap' another object and intercept its operations. The two most common of these are to get and set the values stored in the object, as shown below:

a) Syntax

Here's how the Javascript Proxy is used:

The object is initialized just like any other object in Javascript, using a 'new' operator and assigning it to a variable.

b) Parameters

Proxy requires two parameters:

  • < target >: the original object that is to be proxied
  • < handler >: an object describing the list of interceptable methods or operations (that can be redefined).

Therefore, we would build "traps" into our proxy object to catch these operations and carry out any functionality we might need. There are thirteen of these traps available.

To use the proxy over the above example, with the same standard functionality of get and set, something like this would be done:

We define our proxy using the constructor with the target and handler objects as the parameters. At that point, we can use the proxy object as a reference when accessing and setting values for the original target object, obj. This is done by using the traps (discussed in the next section) like get() and set() which are functions describing the alternate implementation or redefinition of the original operations.

Another example is where we show a use case of using a proxy Object, where we are changing the response that a typical obj.prop operation may have provided.

Output:

Here also it can be seen that the original get method which would have just provided the request value, is redefined to also include a statement 'The property has been read' which is printed on the console.

JavaScript Proxy Traps

Javascript Proxy Traps are the functions of the handler object which intercept its fundamental operations and redefine their behaviour for the corresponding internal method of the original object. For example, the get() trap redefines the operation of the [[get]] internal method of the original object.

The JavaScript specification includes a so-called "internal method" for most operations on objects that explains how they operate at the most fundamental level. For instance, [[Get]], the internal property reading method, [[Set]], the internal property writing method, and so on. These methods can only be called by name from the specification; they are not directly accessible.

Proxy traps intercept the invocation of these methods. Some of these traps are discussed below:

The get() trap

When a property of the target object is accessed through the proxy object, the get() trap is triggered.

Typically, you can create your custom logic in the get() trap.

For instance, you can define calculated properties for the target object using the get() trap. The computed properties are those whose values are determined by subtracting their values from those of other attributes.

As an example: With the date of the birth property, the current age of the user can be calculated using the current time, and accessed by the user.

Another example: Given the first name and last name properties of a user object, a new property can be accessed whose value is computed by the proxy by concatenating them. This is shown in the code below:

Here whenever the property asked for is completeName, the concatenation of first name and last name is provided as output.

The set() Trap

When a property of the target object is set, the set() trap regulates how the object behaves.

Consider an object related to the account of a user, which should have a minimum balance of 1000 rupees. We can impose this condition with the help of a Javascript proxy.

For the statement

The output is:

And for the statement

The output is:

No error occurs if we set the balance as 2000, for example.

The apply() Trap

The apply() is the trap for a function call. For example,

Output:

In the above code, the apply() calls the function to concatenate the first and last names and the result is then converted to lowercase.

The construct() Trap

Handler.construct() is a function for the new operator that enables programmers to build an instance of an object. The method's return value of the construct must be an object.

Here the parameter new target is the constructor proxy originally called, while args refers to the list of arguments for the constructor and the target refers to the target object.

The deleteProperty() Trap

The Handler.delete() method is a delete operator trap. A Boolean value is always returned. This shows whether or not the item that is supposed to be deleted was deleted.

The above code shows how the deleted status of a property can be logged onto the console, by modifying the implementation of deleteProperty to include this extra status information.

Some more traps are:

  • getPrototypeOf – traps an internal call to [[GetPrototypeOf]]
  • setPrototypeOf – traps a call to Object.setPrototypeOf
  • isExtensible – traps a call to Object.isExtensible
  • preventExtensions – traps a call to Object.preventExtensions
  • getOwnPropertyDescriptor – traps a call to Object.getOwnPropertyDescriptor

Javascript Proxy Handlers

Javascript Proxy Handler is the object which contains the traps that redefine the proxy's behaviour. The object is passed as the second argument to the proxy constructor.

Trap methods are applied to the handler objects to redefine the behaviour of the related internal method. For example, handler.get() in the proxy will intercept the [[get]] internal method of the proxied object.

Javascript Proxy Methods

The Internal Methods of an Object are defined to specify how the object should be interacted with when these methods are called. No language provides a direct way to manipulate or handle the data of its objects or arrays, but by calling these internal object methods. For example, for an object obj, obj.x will call the [[Get]] internal method, and the implementation of this method determines the result of this operation. Proxy allows this implementation to change, i.e. obj.x doing some other computation than what is written in [[Get]], with the help of traps. Each internal method is associated with a Proxy Trap, some of which have been discussed earlier.

Objects contain many such internal methods, described below and their corresponding traps.

Internal MethodCorresponding Trap
[[Get]]get()
[[Set]]set()
[[GetPrototypeOf]]getPrototypeOf()
[[SetPrototypeOf]]setPrototypeOf()
[[IsExtensible]]isExtensible()
[[PreventExtensions]]preventExtensions()
[[GetOwnProperty]]getOwnPropertyDescriptor()
[[DefineOwnProperty]]defineProperty()
[[HasProperty]]has()
[[Delete]]deleteProperty()
[[OwnPropertyKeys]]ownKeys()

Function objects contain the following internal methods as well, along with the above ones:

Internal methodCorresponding trap
[[Call]]apply()
[[Construct]]construct()

Any interaction with the object reduces to calling one of these internal methods, which can also be redefined by proxies. Hence, the behaviour of any operation of the object is not dependent on the language but on the object itself. For example, deleting obj.x can log something, or change any global state or other things, and it's not fixed by the language.

JavaScript Proxy Uses and Examples

Here we discuss some examples where Javascript Proxy can be useful.

Default Values

When an asked property of an object or a value in an array is not yet defined, we can provide default values. See the example given below:

The above code provides a default value of 0 when the asked property is not present.

Validation

As discussed earlier also, a Javascript proxy can be used for validating the data before writing or storing them in the object or array.

As shown in the above code, the provided data is set only when it follows the constraints set for the data to be successfully stored in the object or array.

Read Only View

Using a javascript proxy, it is possible to let the object or array be immutable and hence be read-only, whose values cannot be changed or set.

The above code denies the ability to set any value in the object or array and ensures that the data can only be read.

Manipulating DOM Nodes

Javascript proxy is frequently used in DOM Manipulation. Here we discuss one such example where a Proxy is used to toggle an attribute of two different DOM elements.

We create a proxy for an object with a property selected, which reflects the DOM element under focus, or selected view. When an element is assigned to the selected property, the aria attribute of the assigned element is set to true. When a different element is assigned to the selected property, the aria property of this element is set to true and the previous element's aria property is set back to false.

Advantages and Disadvantages of Using Proxies

Advantages

As discussed, Javascript Proxy can be advantageous in many use cases. They are listed below:

  • More control over how objects can be interacted with Proxies provide flexibility and more power over handling the implementation of fundamental operations of objects

  • Validation : Making checks and validating the data, can be type-checking or allowing values in a certain threshold only

  • Security : They allow a read-only view of data contained within objects and arrays, and this prevents unauthorized manipulation of data.

DOM Manipulation

They are actively used in the DOM Manipulation process.

Default Behaviour

Proxies provide the possibility of redefining the get method to produce default values if the properties or data asked, are not present

Disadvantages

On the other hand, it also has some issues that may make it unfavourable in certain situations. In this section, we go through the disadvantages of Javascript Proxy.

Performance

The Proxy acts as a mediator between the original object and the user. This adds an extra layer of complexity in the processing, and hence an overhead to performance. In cases when performance is a critical factor, the proxy can be a very bad choice.

No Operation proxy Forwarding cannot manipulate DOM Elements

No operation proxy forwarding refers to the method in which all the functionality and operations of the target object are forwarded using a proxy. This can be achieved by keeping the handler function of the proxy empty. The code for the same is shown below:

However, this forwarding would work for regular objects but not DOM nodes. For example, the following code produces an error.

The reason for this issue with DOM Nodes is that the this value used internally in the DOM process, refers to the proxy object rather than the original target object.

Browser Compatibility

ChromeEdgeSafariFirefoxOperaChrome for AndroidFirefox for AndroidOpera AndroidSafari on iOSSamsung Internet
Proxy (version)4912101836491836105.0
Proxy() constructor4912101836491836105.0

FAQs

Q.When can we use proxies?

A. When more functionality is required than just the fundamental operations of an object or array, proxies should be used. This can include extra logging of relevant information, in DOM Manipulation, to encapsulate the original object and allow access through only specially designed proxy object methods, allowing newly derived properties to produce a result that normal objects aren't capable of doing.

Q.What can be the issues while using proxies?

A. Proxies add a layer of complexity, and hence should be avoided in performance critical systems. They often slow down the system, but everything comes with a drawback. If you may be failing to see a proxy working, you must check if the operations are related to DOM Manipulation. If the handler object is empty, i.e. there are no traps, the proxy fails to work. The proxy should be avoided if only the default operations are required, else traps must be defined.

Q. What if I don't want to completely redefine but augment some behaviour to an operation?

A. The Reflect API comes to the rescue. This API provides access to the default behaviour of the object and array operations. Hence, the new code can just be added along with this API's methods.

Conclusion

In this article, we discussed Javascript Proxy in detail.

  • Proxy objects wrap other objects and intercept their fundamental operations
  • Proxy allows to customize and have more control over the interaction with the object properties and arrays
  • Proxy takes two parameters, first is the target object to be proxied, and second the handler object
  • The handler object contains operations, called traps, that redefine the behaviour of the operations for the target object
  • There are thirteen traps available, each of which helps to manipulate the operations in some way or the other
  • The get() trap is used to manipulate the reading of data, while the set() trap is used to customize the writing of the data. get() and set() are the most commonly used traps
  • Javascript proxy can be used to validate data, ensure security by making read-only objects, get default values, etc
  • They add overhead to performance, and cannot work with DOM objects