在代理处理程序中,如何区分获取属性(var)与调用方法?

kon*_*dos 4 javascript ecmascript-6

我有以下代码,其中我使用代理对象(代理)来尝试捕获方法调用和属性访问:

示例: https: //jsfiddle.net/r8j4fzxL/2/

(function() {
    'use strict';
    console.clear();

    //some empty class where I want to trap methods props
    class X {
        //...
    }

    let proxy = {
        get: function(target, prop, receiver) {

            console.log('get called: ',
                'target:', target,
                'prop:', prop,
                'receiver:', receiver
            );
            //this is OK, if we are called as a method.
            //but it isn't when called as .prop - because, obviously, we return a function here.
            return function(...args) {
                console.log('wrapper args:', args);
                return 42;
            }
        },


    };


    let p1 = new Proxy(X, proxy);
    //how to distinguish the two in the above proxy:
    console.log(p1.test('some arg passed'));
    console.log(p1.test);
})();
Run Code Online (Sandbox Code Playgroud)

我这里有两个问题。

  1. 一般来说,如果我想捕获属性访问和方法访问,这是正确的方法吗?或者也许我应该以某种方式使用 .apply trap (尽管没有这样做)?

  2. 如果这是正确的方法(使用 .get) - 那么我怎么知道用户如何访问......东西?通过.foo;还是通过.foo();?

我使用但显然不完全理解的资源:

SO:JavaScript 等价于 PHP __call

Enr*_*que 8

这实际上是这个问题的解决方案(它被标记为与此重复,但不是!!):How to get function argument in a Proxy handler

您无法在“get”陷阱中获取参数,因为当调用 get 陷阱时,函数还没有被调用!
但是您可以使用“apply”陷阱创建另一个代理,示例如下:

(function () {
  "use strict";
  console.clear();

  //some empty class where I want to trap methods & props
  class X {}

  let proxy = {
    get: function (target, prop, receiver) {
      console.log(arguments); //this gives the arguments of the 'get' trap itself.

      // normally you trap an existent funcion, in this example we are creating a new one here
      var F = function (...args) {
        console.log("Original function call", args);
      };

      return new Proxy(F, {
        apply: function (target, thisArg, argumentsList) {
          // here you have the arguments
          console.log("Trapped function call", argumentsList);
          return target.apply(thisArg, argumentsList);
        },
      });
    },
  };

  let p = new Proxy(X, proxy);
  console.log(p.test("some arg passed"));
})();

Run Code Online (Sandbox Code Playgroud)

因此,技巧是首先使用 get 捕获函数,而不是返回原始函数,而是使用 apply trap 到原始函数返回一个 Proxy。