Handler objects and proxy objects in JavaScript
This post will discuss about handler objects and proxy objects in JavaScript.
A handler object in JavaScript is an object that defines how a proxy object behaves when certain operations are performed on it. A proxy object is a wrapper around another object that allows us to intercept and modify its properties and methods. A handler object has properties that are functions, called traps, that correspond to different operations. For example, the get trap is a function that runs when a property of the proxy object is accessed, and the set trap is a function that runs when a property of the proxy object is assigned a value. A handler object can have any or all of the following traps:
get(target, prop, receiver): This trap is invoked when getting a property value of the proxy object. It receives the target object, the property name, and the proxy object as arguments. It can return any value.set(target, prop, value, receiver): This trap is invoked when setting a property value of the proxy object. It receives the target object, the property name, the new value, and the proxy object as arguments. It can return a boolean value indicating whether the assignment was successful or not.has(target, prop): This trap is invoked when checking if a property exists on the proxy object using the in operator. It receives the target object and the property name as arguments. It can return a boolean value indicating whether the property exists or not.deleteProperty(target, prop): This trap is invoked when deleting a property of the proxy object using the delete operator. It receives the target object and the property name as arguments. It can return a boolean value indicating whether the deletion was successful or not.ownKeys(target): This trap is invoked when getting the list of own property names of the proxy object usingObject.getOwnPropertyNames()orObject.getOwnPropertySymbols(). It receives the target object as an argument. It can return an array of strings or symbols representing the property names.getOwnPropertyDescriptor(target, prop): This trap is invoked when getting the property descriptor of a property of the proxy object usingObject.getOwnPropertyDescriptor(). It receives the target object and the property name as an argument. It can return an object representing the property descriptor or undefined if the property does not exist.defineProperty(target, prop, descriptor): This trap is invoked when defining or modifying a property of the proxy object usingObject.defineProperty()orObject.defineProperties(). It receives the target object, the property name, and the property descriptor as arguments. It can return a boolean value indicating whether the operation was successful or not.preventExtensions(target): This trap is invoked when preventing further extensions of the proxy object usingObject.preventExtensions(). It receives the target object as an argument. It can return a boolean value indicating whether the operation was successful or not.getPrototypeOf(target): This trap is invoked when getting the prototype of the proxy object usingObject.getPrototypeOf()or proto. It receives the target object as an argument. It can return an object representing the prototype or null if there is no prototype.setPrototypeOf(target, proto): This trap is invoked when setting the prototype of the proxy object usingObject.setPrototypeOf()or proto. It receives the target object and the new prototype as arguments. It can return a boolean value indicating whether the operation was successful or not.isExtensible(target): This trap is invoked when checking if the proxy object is extensible usingObject.isExtensible(). It receives the target object as an argument. It can return a boolean value indicating whether the object is extensible or not.apply(target, thisArg, args): This trap is invoked when calling the proxy object as a functionusing()operator. It receives the target function, the this value, and an array of arguments as arguments. It can return any value.construct(target, args, newTarget): This trap is invoked when constructing a new instance of the proxy object using new operator. It receives the target constructor function, an array of arguments, and another constructor function that was used in place of target as arguments. It can return an object representing the new instance.
To create a handler object in JavaScript, we can use an object literal with any of these traps as properties. For example:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
// A handler that logs every get and set operation on a proxy let handler = { get: function(target, prop) { console.log("Getting " + prop); return target[prop]; }, set: function(target, prop, value) { console.log("Setting " + prop + " to " + value); target[prop] = value; return true; } }; |
To use a handler object with a proxy object, we need to pass it as an argument to the Proxy constructor along with another argument that represents the target object to be wrapped by the proxy. For example:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// A target object to be wrapped by a proxy let obj = { name: "David", age: 20 }; // A proxy that uses our handler object let proxy = new Proxy(obj, handler); // Testing the proxy proxy.name; // Getting name // "David" proxy.age = 21; // Setting age to 21 // true obj.age; // 21 |
That’s all about handler objects and proxy objects in JavaScript.
Thanks for reading.
To share your code in the comments, please use our online compiler that supports C, C++, Java, Python, JavaScript, C#, PHP, and many more popular programming languages.
Like us? Refer us to your friends and support our growth. Happy coding :)