Thursday 14 July 2016

Reflect.get

The other day when checking the Reflect API in ES6 I found something that seemed a bit strange to me, the receiver parameter that you can pass to Reflect.get(target, propertyKey[, receiver]) . The explanation says:

The value of "this" provided for the call to target if a getter is encountered.

Notice also that when you do a Reflect.get of a "getter" (accessor descriptor), the getter itself will be executed rather than returning you the descriptor.

So if you don't pass a "receiver" the "this" passed to the getter will be the "target", else the "receiver". The logic behaviour for me is the former, that "target" is used as "this", why would I want to pass a different object? Well, after some thinking I realised this is useful for proxies and what I posted about some time ago, using the proxy for internal calls vs using the proxied object. So if you are proxying the access to a getter and then you want that the actions in that getter also go through the proxy, you'll pass the proxy as "receiver". One first thought was that you could end up with some kind of recursion, but it's not like that. Reflect.get(target, propertyKey, receiver) will do a target.propertyKey to get the getter, and then invoke the getter with "receiver" as "this", which is quite different from doing a receiver.propertyKey, that with a proxy would cause recursion. If your getter is calling another getter and so on, in the end one of those getters will be just calling a data descriptor, so the proxying will end.

With all this, I've put a sample with 3 ways to proxy your method/property access. One that will not go through the proxy for internal calls (neiter method nor accessor descriptors), another that will go through the proxy for internal cases for both of them, and finally one that will do it for methods but not for accessors. You can check the code here.

A reminder regarding method calls. Method calls in JavaScript involve 2 actions, getting the function (so if proxying the get trap gets called) and then doing a call to the returned function passing as "this" the object on which you did the "get" (so if you are using a proxy, the proxy will be passed as "this" to the function, this is important for cases 2 and 3 in my sample)

No comments:

Post a Comment