【问题标题】:Run a function when any other class function is called在调用任何其他类函数时运行一个函数
【发布时间】:2021-07-08 08:49:54
【问题描述】:

我有一个具有 100 多个函数的 es6 类。
我添加了一个新函数,每次调用任何其他函数时都必须运行该函数。
我找到了很多解决方案,但没有人解决我的问题...
我知道我可以将此调用添加到每个函数,但我将以重复代码和所有函数的大量工作结束。

这就是我到目前为止所做的:

return class Test {
    constructor () {}

    addedFN() {
         console.log('FN');
    }

    A() {
        this.addedFN();
        console.log('A');
    }

    B() {
        this.addedFN();
        console.log('B');
    }

    C() {
        this.addedFN();
        console.log('C');
    }
    ...
}

正如我们在这种方法中看到的那样,我有很多我想避免的代码重复...
另外,先调用新函数,再在内部调用下一个函数的解决方案是行不通的,因为所有函数在应用程序的很多地方都用到了。

我还尝试在构造函数中运行以下代码,但这是一个糟糕的解决方案,因为我的类被多次调用,然后每次都会运行此代码:

for(const key of Object.getOwnPropertyNames(Test.prototype)) {
 const old = Test.prototype[key];
 Test.prototype[key] = function(...args) {
   addedFN(...args);
   old.call(this, ...args);
 };
}

【问题讨论】:

    标签: javascript ecmascript-6 ecmascript-5


    【解决方案1】:

    不要在构造函数中运行,在类声明之后运行

    此外,该解决方案将导致过多的递归,因为它也适用于addedFn,它将调用addedFn,它将调用addedFn ...等等,直到您的浏览器抛出“太多递归”错误

    所以你也不想将它应用到addedFn

    在下面的代码中,我也没有将它应用于constructor ...但是,即使我这样做了,它也不会在构造对象时调用addedFn,所以,为了更清楚,我明确不碰构造函数

    class Test {
      constructor(y) {
        this.y = y
      }
      fun1(x) {
        console.log('I am fun1', x, this.y);
      }
      fun2() {
        console.log('I am fun2');
      }
      addedFn(...x) {
        console.log('added function', ...x);
      }
    }
    Object.getOwnPropertyNames(Test.prototype).forEach(f => {
      if (f !== 'constructor' && f !== 'addedFn' && typeof Test.prototype[f] === 'function') {
        const old = Test.prototype[f];
        Test.prototype[f] = function(...args) {
          this.addedFn(...args);
          return old.apply(this, args);
        }
      }
    })
    let c = new Test('works');
    c.fun1(1,2,3)

    注意:你还应该测试Test.prototype[f] 是否是一个函数——除非你的类只有函数

    【讨论】:

      【解决方案2】:

      Proxy 可以很好地使用它来透明地更改您的对象,而无需实际更改对象,只需将其包装在代理中。

      get trap 可以检查您是否正在访问方法,然后使用apply trap 将其动态包装到代理中。

      class Test {
          A() { console.log('A'); }
          B() { console.log('B'); }
          C() { console.log('C'); }
          get X() { return 1; }
          Y = 2;
      }
      
      function addedFN() { console.log('FN'); }
      
      const loggingHandler = {
        apply() {
          addedFN();
          return Reflect.apply(...arguments);
        }
      };
      
      const wrapMethods = {
        get() {
          const result = Reflect.get(...arguments);
          if (typeof result === "function")
            return new Proxy(result, loggingHandler);
          return result;
        }
      };
      
      const test = new Test();
      const foo = new Proxy(test, wrapMethods);
      
      foo.A();
      foo.B();
      foo.C();
      console.log(foo.X);
      console.log(foo.Y);
      .as-console-wrapper { max-height: 100% !important; }

      该方法可以概括为接受不同可能的方法修饰符并将它们缓存在WeakMap

      class Test {
          A() { console.log('A'); }
          B() { console.log('B'); }
          C() { console.log('C'); }
          get X() { return 1; }
          Y = 2;
      }
      
      function addedFN() { console.log('FN'); }
      
      const noop = () => {};
      const wrapFunction = ({before = noop, after = noop}) => ({
        apply() {
          before();
          const result = Reflect.apply(...arguments);
          after();
          return result;
        }
      });
      
      const wrapMethods = handler => ({
        _cache: new WeakMap(),
        get() {
          const result = Reflect.get(...arguments);
          if (typeof result === "function") {
            if (!this._cache.has(result))
              this._cache.set(result, new Proxy(result, handler));
              
            return this._cache.get(result);
          }
          
          return result;
        }
      });
      
      const loggingHandler = wrapFunction({before: addedFN});
      
      const test = new Test();
      const foo = new Proxy(test, wrapMethods(loggingHandler));
      
      foo.A();
      foo.B();
      foo.C();
      console.log(foo.X);
      console.log(foo.Y);

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-27
        • 1970-01-01
        • 1970-01-01
        • 2021-04-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-20
        相关资源
        最近更新 更多