混合构造函数并在Javascript代理对象上应用陷阱

Jar*_*ede 6 javascript proxy-pattern ecmascript-6

我有一个类,我想应用代理,观察方法调用和构造函数调用:

Calculator.js

class Calc {
  constructor(){}

  add(a, b) {
    return a+b;
  }

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

module.exports = Calc;
Run Code Online (Sandbox Code Playgroud)

index.js

const Calculator = require('./src/Calculator');

const CalculatorLogger = {
  construct: function(target, args, newTarget) {
      console.log('Object instantiated');
      return new target(...args);
  },
  apply: function(target, thisArg, argumentsList) {
      console.log('Method called');
  }
}
const LoggedCalculator = new Proxy(Calculator, CalculatorLogger);
const calculator = new LoggedCalculator();
console.log(calculator.add(1,2));
Run Code Online (Sandbox Code Playgroud)

当调用它时,我希望输出为:

对象实例化

方法叫做

但是,apply没有被调用,我认为这是因为我将Proxy附加到Calculator类,而不是实例化的对象,所以不知道apply陷阱.

如何在方法调用和构造函数调用上构建一个包含所有代理的"观察"代理.

J. *_*rdo 5

我认为这是因为我将代理附加到计算器类,而不是实例化对象,因此不知道应用陷阱。

你完全正确,代理作用于对象,因此除非调用类的函数属性,否则它不会调用 apply Calculator,如下所示:

class Calculator {
  constructor() {
    this.x = 1;
  }

  instanceFunction() {
    console.log('Instance function called');
  }

  static staticFun() {
    console.log('Static Function called');
  }

}

const calcHandler = {
  construct(target, args) {
    console.log('Calculator constructor called');
    return new target(...args);
  },
  apply: function(target, thisArg, argumentsList) {
    console.log('Function called');
    return target(...argumentsList);
  }
};

Calculator = new Proxy(Calculator, calcHandler);

Calculator.staticFun();

const obj = new Calculator();

obj.instanceFunction();
Run Code Online (Sandbox Code Playgroud)

Calculator清楚了这一点后,您可以执行以下操作来使用代理包装 的实例:

  1. 使用类代理来代理实例construct

const CalculatorInstanceHandler = {
  apply(target, thisArg, args) {
    console.log('Function called');
    return target(...args);
  }
}

const CalculatorClassHandler = {
  construct(target, args) {
    const instance = new target(...args);
    return new Proxy(instance, CalculatorInstanceHandler);
  }
}
Run Code Online (Sandbox Code Playgroud)

  1. 在类中有一个工厂函数Calculator来创建代理实例:

const CalculatorInstanceHandler = {
  apply(target, thisArg, args) {
    return target(...args);
  }
};

class Calculator {

  static getNewCalculator() {
    const instance = new Calculator();

    return new Proxy(instance, CalculatorInstanceHandler);

  }
}
Run Code Online (Sandbox Code Playgroud)