Reputation: 3169
I have a proxy handler like this:
let handler = {
get: function(target, name) {
let member = target[name];
if (typeof member === 'function') {
return function() {
//
}
}
return member;
}
}
Whenever a method is called on Proxy object:
var obj = {
foo: function() {
//
}
}
var p = new Proxy(obj, handler);
p.foo();
...It invokes the function that was returned from the handler
's getter. But the problem is, when the method is accessed rather than invoked like this:
p.foo;
The entire definition of the function is returned.
Is there any way by which I could check to see if the method is being accessed (p.foo
) or invoked (p.foo()
)? I am trying to achieve something like:
if (typeof member === 'function' && member.isBeingCalled()) {
return function() {
//
}
}
Also, in case of p.foo
, I would like to return the definition of member
instead of the function that handler's getter returns.
Upvotes: 4
Views: 719
Reputation: 1618
Another way is to wrap it in another function in get
. Then you can decide to call the real method or not:
const obj = {
someMethod: () => {
console.log("I'm invoking");
},
};
const handler = {
get(target, prop, receiver) {
if (prop === "someMethod") {
//here is a wrapper for your target[prop] method
return () => {
console.log("This method is called! Do something!");
target[prop]();
};
}
},
};
const proxyObj = new Proxy(obj, handler);
proxyObj.someMethod; //nothing interesting - just access function literal
proxyObj.someMethod(); //This method is called! Do something! I'm invoking
Upvotes: 1
Reputation: 31833
Yes, this is possible but in order to make it work you need to consider what happens when call a method
o.foo()
as there is more going on than you might think.
The first operation is a property lookup that retrieves the value of the property having the key "foo"
from the object o
. Now, the value retrieved is itself an object, specifically a function object.
The second operation is the invocation of that function as a method by way of
function.prototype.apply. What this does is invoke the function with its this
value bound to o
.
Therefore, in order to achieve the desired behavior, one must proxy the value of the property o.foo
rather than o
itself. your proxy will use the apply trap to intercept and modify the invocation of the function what is the value of that property. This is described well by MDN.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/apply
Essentially you would write something like
const foo = o.foo;
const proxiedFoo = new Proxy(foo, {
apply(target, thisArg, argumentsList) {
if (thisArg) {
// this function is being invoked as a method
}
}
});
o.foo = proxiedFoo;
Upvotes: 2