javascript中的拦截函数调用

时间:2019-01-13 18:21:24

标签: javascript node.js function proxy

PHP的__call魔术方法相当于什么?

给我的印象是Proxy可以做到,但不能做到。

class MyClass{
  constructor(){
    return new Proxy(this, {
      apply: function(target, thisArg, args){
        console.log('call', thisArg, args);
        return 'test';
      },

      get: function(target, prop){
        console.log('get', prop, arguments);
      }


    });

  }

}

var inst = new MyClass();
console.log(inst.foo(123));

get似乎可以正常工作,因为我看到“ get foo”,但是apply无效。我得到的不是函数错误。

3 个答案:

答案 0 :(得分:2)

apply实际上处理对对象本身的函数调用 ,即,如果您执行new Proxy(someFunction, { apply: ... }),则apply将在someFunction被调用之前被调用叫。

没有任何东西可以捕获对属性的调用,因为这将是多余的– get已经在返回属性时进行处理。您可以简单地返回一个函数,该函数在被调用时会产生一些调试输出。

class MyClass{
  constructor(){
    return new Proxy(this, {
      get: function(target, prop) {
        return function() {
          console.log('function call', prop, arguments);
          return 42;
        };
      }
    });
  }
}

var inst = new MyClass();
console.log(inst.foo(123));

答案 1 :(得分:1)

是的代理服务器可以做到这一点,但是即使在捕获方法时,也必须使用代理服务器的get

然后在这里我也执行您的真实方法,但是我不知道您是否要模拟它。

class MyClass {
  constructor() {
    return new Proxy(this, {
      get(target, prop, receiver) {
        if (typeof target[prop] !== "function") {
          return "etcetcetc";
        }
        return function(...args) {
          console.log('call', args);
          return target[prop]();
        };
      }
    });
  }

  foo() {
    console.log('I am foo!');
  }
}

var inst = new MyClass();
inst.foo(123);

如您所见,如果您正在调用实例的方法,我将对其进行拦截,然后返回原始方法执行。

如果您正在访问实例的属性,我将始终返回一个模拟字符串。

然后当然要用您想要的行为对其进行更改。

答案 2 :(得分:1)

这是实现您所要求的另一种方式。

class MyClass{
  constructor(){
     return new Proxy(this, {
        get(target, propKey, receiver) {
            const origMethod = target[propKey];
            return function (...args) {
                let result = origMethod.apply(this, args);
                console.log(propKey + JSON.stringify(args)
                    + ' -> ' + JSON.stringify(result));
                return result;
            };
        }
    });
  }
  
foo = (x) => {
  return x + 1;
};

}

var inst = new MyClass();
console.log(inst.foo(123));