我有一个像这样的代理处理程序:
let handler = {
get: function(target, name) {
let member = target[name];
if (typeof member === 'function') {
return function() {
//
}
}
return member;
}
}
每当在 Proxy 对象上调用方法时:
var obj = {
foo: function() {
//
}
}
var p = new Proxy(obj, handler);
p.foo();
...它调用从
handler
的 getter 返回的函数。但问题是,当该方法是accessed而不是invoked时,如下所示:
p.foo;
返回函数的完整定义。
有什么方法可以检查该方法是否正在被访问(
p.foo
)或调用(p.foo()
)?我正在努力实现类似的目标:
if (typeof member === 'function' && member.isBeingCalled()) {
return function() {
//
}
}
另外,对于
p.foo
,我想返回 member
的定义,而不是处理程序的 getter 返回的函数。
是的,这是可能的,但为了使其工作,您需要考虑调用方法时会发生什么
o.foo()
因为发生的事情比你想象的要多。
第一个操作是属性查找,从对象
"foo"
检索具有键 o
的属性的值。现在,检索到的值本身就是一个对象,特别是函数对象。
第二个操作是通过以下方式调用该函数作为方法 函数.原型.应用。其作用是调用该函数,并将其
this
值绑定到 o
。
因此,为了实现所需的行为,必须代理属性
o.foo
的值而不是 o
本身。您的代理将使用 apply trap 来拦截和修改函数的调用,即该属性的值是什么。 MDN 对此有很好的描述。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/apply
基本上你会写类似的东西
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;
如果你想确定你的对象方法是否已被调用或刚刚被访问,你可以将其包装在另一个函数中:
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