JavaScript has a special built-in Proxy object that can be used to control access to the properties of almost any object. Although this isn't often needed in application code, Proxy is used regularly in libraries and frameworks. Here are just a few examples of how it's used: overloading certain operators, mock objects, message passing, tracking changes (usually in application state management), validation, logging, caching, and more.
The object is used like this: the object is created, two parameters are passed to its constructor (more about them below), and then all the work with the original object is done via the proxy object that was created.
const proxy = new Proxy(target, handler);
The first parameter (target
) - is the object that you want to make a proxy for. The second parameter (handler
) is an object with handlers that intercept various operations on the original object (target
).
Let's look at a simple example where Proxy returns the default value if the property does not exist:
// Number of users in different countries
const usersCountByCountry = {};
const handlers = {
get: (target, prop) => {
// in - checks the presence of a property along a whole chain of prototypes
// In the case of Proxy, this is better than _.has
if (prop in target) {
return target[prop];
}
return 0;
},
};
// obj - wraps the original object
const obj = new Proxy(usersCountByCountry, handlers);
obj.australia; // 0
obj.australia += 1; // 1
obj.usa; // 0
Proxy wraps the source object and intercepts requests to it. This is done using handlers called traps. Traps are defined as methods of an object that's passed as the second parameter to the Proxy constructor.
There are a total of 13 traps in Proxy, with "get" and "set" being the most commonly used ones. They're used to intercept all read (get) and write (set) operations.
The get trap is called whenever any object property is accessed. It takes the source object and the name of the property to be accessed as input. Inside, you can build any kind of logic. In our example, we return the value of the property from target
if it exists, and 0
if it doesn't.
get: (target, prop) => {
if (prop in target) {
return target[prop];
}
return 0;
},
Now let's look at the set trap example:
const student = {
name: 'John',
age: 23,
program: 'js-frontend',
};
const rewrite = new Proxy(student, {
set(target, prop, value) {
// if the property is in the object, proxy allows us to rewrite it
if (prop in target) {
target[prop] = value;
// if the writing goes successfully, the set() method should return true
return true;
} else {
// if the property isn't in the object, an error will be thrown, or we can return false
throw new Error(`Cannot rewrite non-existed property '${prop}'`);
}
},
});
Now, if you assign a value to a non-existent property in an object, there'll be an error:
// If you try to change a property that doesn't exist, there'll be an error:
rewrite.country = 'Australia';
// Error: Cannot rewrite non-existed property 'country'
// If the property already exists, there won't be an error:
rewrite.name = 'Alex';
console.log(student);
// => { name: 'Alex', age: 23, program: 'js-frontend' }
Conceptually, Proxy is the kind of thing that mustn't stand out. The application code mustn't know that it's working with a Proxy, not a source object. Only then will it be possible to work transparently with Proxy, i.e., you won't have to tweak the code for it. This is partly the responsibility of the programmer and partly the responsibility of Proxy. Therefore:
- Proxy has no properties of its own, it always proxies calls
- It's impossible to retrieve a source object from Proxy and change it somehow to bypass the traps
- According to the specification, there's no way to determine if an object is a proxy (technically it is possible, but generally, there's no reason to be using it).
Recommended materials
Are there any more questions? Ask them in the Discussion section.
The Hexlet support team or other students will answer you.
For full access to the course you need a professional subscription.
A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.