Let's say we have the following class declaration:
class Dog {
#name
set name(n) {
if(n ==="abc" ) {
throw new Error("Provide a longer name")
}
this.#name = n
}
get name() {
return this.#name
}
}
The name
property is marked as a private filed.
We want to add a Javascript proxy so that we can intercept and modify the behavior of the set name()
method. We want to add an extra validation condition:
let handler = {
set: (obj, property, value) => {
if (property.length < 2) {
throw new Error("The name should be longer than 2 characters.")
}
return obj[property] = value
}
};
let d = new Dog()
const proxyedDog = new Proxy(d, handler)
proxyedDog.name = "abc"
However, there are 2 problems with this approach:
- having the
obj[property] = value
will mess up the initial intention of the setter when we doproxyedDog.name = "abc"
- if we try to access the name attribute, by loging
proxyedDog.name
we will get the bellow error:
console.log(proxyedDog.name)
//Uncaught TypeError: Cannot read private member #name from an object whose class did not declare it
Using the Reflect API to invoke the original getters and setters from a Javascript proxy
Both of the above problems will be solved if we find a way to access the original getters and setter methods from within the proxy.
Here comes into play the Javascript Reflect API.
All of the methods of the Reflect class are static so they will be invoked with syntax like Reflect.doStuff()
.
It works by giving it an object and asking it to call something from it. So, for example, if we want to call a setter we will have:
Reflect.set(obj, property, paramter)
Steve Griffith has a great video explaining more about the Reflect API:
With this in mind, we can now update our proxy as this:
let handler = {
set: (obj, property, value) => {
if (property === 'name') {
throw new Error("Provide a longer name")
}
return Reflect.set(obj, property, value)
},
get: (obj, property, value) => { return Reflect.get(obj, property)}
};
This will fix both the setter and getter by calling their initial form.
Using the Reflect API to invoke any method from a Javascript proxy
As a final note when using the Reflect API we are not limited just to setters and getters. We can call any method by using the apply
method:
Reflect.apply(target, thisArgument, argumentsList)
📖 50 Javascript, React and NextJs Projects
Learn by doing with this FREE ebook! Not sure what to build? Dive in with 50 projects with project briefs and wireframes! Choose from 8 project categories and get started right away.
📖 50 Javascript, React and NextJs Projects
Learn by doing with this FREE ebook! Not sure what to build? Dive in with 50 projects with project briefs and wireframes! Choose from 8 project categories and get started right away.