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

时间:2019-06-02 05:35:32

标签: javascript es6-proxy

我有这样的代理处理程序:

let handler = {
        get: function(target, name) {
            let member = target[name];
            if (typeof member === 'function') {
                return function() {
                    //
                }
            }
            return member;
        }
    }

只要在代理对象上调用方法:

var obj = {
    foo: function() {
        //
    }
}

var p = new Proxy(obj, handler);
p.foo();

...它调用从handler的getter返回的函数。但是问题是,当这样访问而不是调用这种方法时:

p.foo;

返回函数的整个定义。

有什么方法可以检查该方法是正在访问(p.foo)还是被调用(p.foo())?我正在尝试实现以下目标:

if (typeof member === 'function' && member.isBeingCalled()) {
    return function() {
        //
    }
}

另外,对于p.foo,我想返回member的定义,而不是处理程序的getter返回的函数。

1 个答案:

答案 0 :(得分:0)

是的,这是可能的,但是为了使其起作用,您需要考虑调用方法时发生的事情

 o.foo()

发生的事情比您想象的要多。

第一个操作是属性查找,它从对象"foo"中检索具有键o的属性的值。现在,检索到的值本身就是一个对象,特别是一个函数对象。

第二个操作是通过以下方式调用该函数作为方法 function.prototype.apply。这样做是通过将this的值绑定到o来调用函数。

因此,为了实现所需的行为,必须代理属性o.foo的值,而不是o本身的值。您的代理将使用Apply陷阱来拦截和修改该函数的调用,该属性的值是多少。 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;