In JavaScript, a Proxy object is an essential feature that allows developers to intercept and customize fundamental operations of another object.
It enables the creation of a wrapper around the existing object to provide additional functionality or behavior. A Proxy object has a target object and a handler object, which provides traps that intercept the fundamental operations performed on the target object.
Creating a new Proxy object involves passing two arguments to the Proxy constructor function, the target object, and the handler object.
The target object is the object that you want to wrap, while the handler object is an object containing functions that intercept and modify the behavior of fundamental operations performed on the target object.
Here is an example of creating a new Proxy object in JavaScript:
// Define the target object
const target = {
name: "John",
age: 25,
};
// Define the handler object
const handler = {
get: function (target, prop, receiver) {
console.log(`Getting ${prop}`);
return Reflect.get(target, prop, receiver);
},
set: function (target, prop, value, receiver) {
console.log(`Setting ${prop} to ${value}`);
return Reflect.set(target, prop, value, receiver);
},
};
// Create the proxy object
const proxy = new Proxy(target, handler);
In the code above, we define the target object with two properties, name, and age. We then define the handler object containing two functions, get and set. The get function is called when a property of the target object is accessed, while the set function is called when a property of the target object is set. In both functions, we log a message to the console to indicate the operation being performed, and we use the Reflect object to perform the operation on the target object.
To create the proxy object, we pass the target object and the handler object to the Proxy constructor function. The proxy object is now a wrapper around the target object and will intercept any fundamental operations performed on it.
Let’s explore some of the traps available in the handler object and how they can be used to modify the behavior of the target object.
The get
trap:
The get
trap is called when a property of the target object is accessed. It takes three arguments, the target object, the property name, and the proxy object itself.
const target = {
name: "John",
age: 25,
};
const handler = {
get: function (target, prop, receiver) {
console.log(`Getting ${prop}`);
return Reflect.get(target, prop, receiver);
},
};
const proxy = new Proxy(target, handler);
console.log(proxy.name); // "Getting name" is logged to the console
console.log(proxy.age); // "Getting age" is logged to the console
In the example above, we intercept any access to the properties of the target object using the get
trap. We log a message to the console indicating the property being accessed and return the value of the property using the Reflect.get
function.
The set
trap:
The set
trap is called when a property of the target object is set. It takes four arguments, the target object, the property name, the new value, and the proxy object itself.
const target = {
name: "John",
age: 25,
};
const handler = {
set: function (target, prop, value, receiver) {
console.log(`Setting ${prop} to ${value}`);
return Reflect.set(target, prop, value, receiver);
},
};
const proxy = new Proxy(target, handler);
proxy.name = "Jane"; // "Setting name to Jane" is logged to the console
proxy.age = 30; // "
In the example above, we intercept any attempt to set the properties of the target object using the set
trap. We log a message to the console indicating the property being set and the new value, and we update the value of the property using the Reflect.set
function.
The has
trap:
The has
trap is called when the in
operator is used on the target object to check if a property exists. It takes two arguments, the target object and the property name.
const target = {
name: "John",
age: 25,
};
const handler = {
has: function (target, prop) {
console.log(`Checking if ${prop} exists`);
return Reflect.has(target, prop);
},
};
const proxy = new Proxy(target, handler);
console.log("name" in proxy); // "Checking if name exists" is logged to the console
console.log("email" in proxy); // "Checking if email exists" is logged to the console
In the example above, we intercept any use of the in
operator on the target object using the has trap. We log a message to the console indicating the property being checked, and we return the result of the operation using the Reflect.has
function.
The apply
trap:
The apply
trap is called when a function is invoked on the target object. It takes three arguments, the target object, the this
value, and an array of arguments.
const target = {
add: function (a, b) {
return a + b;
},
};
const handler = {
apply: function (target, thisArg, args) {
console.log(`Calling function ${target.name} with arguments ${args}`);
return Reflect.apply(target, thisArg, args);
},
};
const proxy = new Proxy(target.add, handler);
console.log(proxy(2, 3)); // "Calling function add with arguments 2,3" is logged to the console, and the result 5 is returned
In the example above, we intercept any invocation of the add
function on the target object using the apply
trap. We log a message to the console indicating the function being called and the arguments, and we return the result of the operation using the Reflect.apply function.
These are just a few examples of the traps available in the handler object. Other traps include construct
for creating new objects using the new
operator, getOwnPropertyDescriptor
for getting the descriptor of a property, defineProperty
for defining new properties on the object, and many more.
Thank you for reading, and let’s have conversation with each other
Thank you for reading my article. Let’s have conversation on Twitter and LinkedIn by connecting.