【问题标题】:reflection appears to be losing this反射似乎正在失去这个
【发布时间】:2018-07-06 15:27:24
【问题描述】:

我正在尝试为我的类构建 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();

还有一个需要单例的类

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 不是函数

【问题讨论】:

  • this.otherClass().shoutOut();
  • @JonasW。你的意思是放那个吗?我不认为这是正确的?
  • 你试过了吗?!
  • @JonasW。 otherClass 是一个类,没有new 怎么称呼它? @Jarede,我想你想要this.otherClass = new otherClass();。另外,尝试将apply 更改为result = Reflect.apply(result, target, args);
  • otherClass 是一个单例,它已经将自己导出为new OtherClass();

标签: javascript ecmascript-6 es6-proxy


【解决方案1】:

您的问题是您的代理总是为任何被访问的属性返回一个函数,包括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 陷阱,因为您的实例都不是函数。

【讨论】:

  • 你为什么选择orig.apply而不是Reflect.apply
  • @Jarede 主要是因为apply跟代理无关,只是普通的函数装饰而已。
  • 所以使用Reflect.apply 应该不会引起问题?我敲了这个runkit.com/5a7af2d1bd09580012f31fc2/5b43584ff93f080011766477,它适用于Reflect.apply,但不适用于orig.apply
  • @Jarede 在target 而不是this 上调用它是错误的,这会隐式绑定方法。
  • 那么我将如何解决该代码示例中的问题?您的代码“看起来”像是破坏了它,而我的代码返回了我所期望的。
猜你喜欢
  • 2021-12-05
  • 2011-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多