Hi There,
I am on the stage for the second part of the Javascript Proxy article. If you did not read the first part, I highly recommend you read it first. Part1
I want to talk about Reflect API
and its relation with Proxy
today.
Reflect
is a built-in object that simplifies the creation of Proxy.
It was said that internal methods, such as [[Get]]
, [[Set]]
and others are specification-only, they can’t be called directly.
The Reflect object makes that somewhat possible. Its methods are minimal wrappers around the internal methods.
Here are examples of operations and Reflect calls that do the same
const user = {};
Reflect.set(user, 'name', 'John'); //is same as user.name = "John";
console.log(user.name); // John
When we normally set the user name as user.name = "Chety";
what is being done behind the scenes Javascript calls its internal [[Set]]
method. As we said earlier in this article, these methods are internal and can not be called directly but somehow Reflect API
make it possible. Reflect API
has corresponding methods for Javascript internal methods(set
for [[Set]]
, get
for [[Get]]
. Pretty intuitive right?). That means as you call Reflect.set(...)
, Reflect API
will forward this call to the original object which is the internal [[Set]]
method in this case.
We can use Reflect
it with Proxy
also. Below you can find a proxy creation for user
. As always explanations will be provided with code :)
let user = {
name: "Rodik"
}
user = new Proxy(user, {
get(target,prop,receiver){
console.log(`GET ${prop}`);
//Reflect forwards operation to the original object
return Reflect.get(target,prop,receiver); // or Reflect.get(...arguments)
},
set(target,prop,value,receiver){
console.log(`SET ${prop} = ${value}`);
//returning a truthy value means success. Otherwise
//update operation will not take place
return Reflect.set(target,prop,value,receiver)
}
})
user.name; //GET name
user.name = "Miran"; //SET name = Miran
For every internal method, trappable by Proxy, there’s a corresponding method in Reflect, with the same name and arguments as the Proxy trap.
Let us see some code examples, which can be tricky when not used Reflect
with Proxy
.
let role = {
_name: "generic role",
get name(){
return this._name
}
}
role = new Proxy(role,{
get(target,prop,receiver){
console.log(`GET METHOD CALLED.`);
return target[prop]
}
})
console.log(role.name); // GET METHOD CALLED. generic role
const admin = {
__proto__: role,
_name: "admin"
}
console.log(admin.name); //it prints generic role , but why ?
In the above code, we expect admin.name
as admin
but what we got is generic role
. It is not what we expected. The reason lies in the Proxy
mechanism. Since admin
does not have a getter method or property called name
, Javascript will look at its prototype which is role
. Role object has a name-getter method thus Javascript calls this getter. That getter method invokes get trap
which is defined by proxy. In our proxy get trap target is still role
and role["name"]
returns what? Wait for it... Of course generic role
. So is the case resolved? Not quite yet. To solve this issue instead of returning, we should use Reflect.get(...)
for forwarding get operation
to the original object
which in this case is admin
. Our get trap should be like below.
get(target,prop,receiver){
console.log(`GET METHOD CALLED.`);
//forward get operation to the original object
return Reflect.get(target,prop,receiver);
}
That is all I have for you today. If you have any questions, comments, etc... just drop in the comments and I will reply as soon as possible. Until the next post, stay tuned, bye-bye.