确定函数是否在代理处理程序中被访问或调用

问题描述 投票:0回答:2

我有一个像这样的代理处理程序:

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 返回的函数。

javascript es6-proxy
2个回答
2
投票

是的,这是可能的,但为了使其工作,您需要考虑调用方法时会发生什么

 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;

0
投票

如果你想确定你的对象方法是否已被调用或刚刚被访问,你可以将其包装在另一个函数中:

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

© www.soinside.com 2019 - 2024. All rights reserved.