You are essentially restating my question: what _are_ the possibilities with proxies? (What can you do with proxies that is much more messy/difficult/verbose to do otherwise?)
class MyArray extends Array {
constructor(...args) {
super(...args);
return new Proxy(this, {
get: (target, name) => {
if (name && name.match && name.match(/^-\d+$/)) {
return Reflect.get(target, this.length + parseInt(name, 10));
}
return Reflect.get(target, name);
},
set: (target, name, value) => {
if (name && name.match && name.match(/^-\d+$/)) {
return Reflect.set(target, this.length + parseInt(name, 10), value);
}
return Reflect.set(target, name, value);
},
});
}
}
You could accomplish the same thing by creating explicit setters and getters, but proxies allow you to directly intercept and modify the behavior of property access, calling an object like a function, etc. This sort of flexibility allows you to create APIs that wouldn't be possible otherwise.The CustomPage class 'extends' through the use of a proxy a Page and Browser class, while adding its own methods on top. The proxy mediates access to the Custompage instance, and the Page and Browser. When calling a method on CustomPage, it first looks to see if the method exists on the CustomPage instance, then the Browser instance, then the Page.
I had originally wanted to subclass Page, which is implemented by the Puppeteer library, but the Browser class had a dozen direct references to the Page class. I would have had to sublcass the Browser as well and override all those methods to instead reference my CustomPage. The proxy seemed like an appropriate solution.