反射似乎正在失去这个

reflection appears to be losing this

我正在尝试为我的 classes 构建一个 AOP 记录器...我遇到了一个问题,当我返回到目标函数时,该函数无法访问 this

所以我的 AOP 有点像这样

AOP.js

class AOP {
  constructor() {

  }
  static ClassHandler(obj) {
    const InstanceHandler = {
      get(target, prop, receiver) {
        console.log(target.constructor.name);
        const origMethod = target[prop];
        return function (...args) {
          // let result = Reflect.apply(origMethod, this, args)
          let result = Reflect.get(target, prop, receiver)
          result = Reflect.apply(result, this, args);
          console.log(prop + JSON.stringify(args)
              + ' -> ' + JSON.stringify(result));
          return result;
        };
      },
      apply(target, thisArg, argumentsList) {
        console.log('actually applied');
      }
    }

    const handler = {
      construct(target, args) {
        console.log(`${target.name} instantiated`);
        console.log(args);
        const instance = Reflect.construct(...arguments);
        return new Proxy(instance, InstanceHandler);
      }
    }

    return new Proxy(obj, handler);
  }
}

module.exports = AOP;

单身人士

OtherClass.js

class OtherClass {
  constructor() {
    this._blah = 'this is a shoutout';
  }

  shoutOut() {
    console.log(this._blah);
  }
}

module.exports = new OtherClass();

和一个需要单例的class

CalculatorDI.js

class Calculator {
  constructor(otherClass) {
    this.otherClass = otherClass;
  }

  add(a, b) {
    this.otherClass.shoutOut();
    return a+b;
  }

  minus(a, b) {
    return a-b;
  }
}

module.exports = Calculator;

像这样把它们放在一起:

const AOP = require('./src/aspects/AOP');
const Calculator = AOP.ClassHandler(require('./src/CalculatorDI'));
const otherClass = require('./src/OtherClass');
const calculator = new Calculator(otherClass);

calculator.add(1,1);

当运行这个时候,我得到错误:

TypeError: this.otherClass.shoutOut is not a function

你的问题是你的代理总是returns一个函数,对于任何被访问的属性,包括this.otherClass。您将需要使用

const instanceHandler = {
  get(target, prop, receiver) {
    console.log(target.constructor.name);
    const orig = Reflect.get(target, prop, receiver);
    if (typeof orig == "function") {
//  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      return function (...args) {
        const result = orig.apply(this, args);
        console.log(prop + JSON.stringify(args) + ' -> ' + JSON.stringify(result));
        return result;
      };
    } else {
      return orig;
    }
  }
};

另请注意,您不需要 instanceHandler 中的 apply 陷阱,因为 none 个实例是一个函数。