Изменить аргументы функции, используя MethodDecorator, не изменяя «это значение»? - PullRequest
0 голосов
/ 31 августа 2018

Представьте, что вам нужно изменить аргументы метода во время выполнения, используя декоратор. Тривиальный пример, чтобы сделать его простым: все аргументы, установленные в «Hello World»:

export const SillyArguments = (): MethodDecorator => {
  return (
      target: Object,
      propertyKey: string | symbol,
      descriptor: PropertyDescriptor
  ) => {
    const originalMethod = descriptor.value;
    descriptor.value = (...args: any[]) => {
      Object.keys(args).forEach(i => {
        args[i] = 'Hello World';
      });

      return originalMethod.apply(null, args);
    };

    return descriptor;
  }
};

Пример использования:

class TestClass {
  private qux = 'qux';

  @SillyArguments()
  foo(val: any) {
    console.log(val);
    console.log(this.qux);
    this.bar();
  }

  bar() {
    console.log('bar');
  }
}

const test = new TestClass();
test.foo('Ciao mondo'); // prints "Hello World"

TypeError: Невозможно прочитать свойство 'qux' с нулевым значением

Проблема здесь apply(null, args), которая меняет контекст this. Это делает невозможным вызов переменной экземпляра с именем qux изнутри foo().

Другая возможность - изменить вызов на originalMethod.apply(target, args), но на этот раз qux равен undefined, тогда как bar() можно вызвать.

Есть ли возможность вызвать originalMethod с контекстом this, правильно установленным для экземпляра?

1 Ответ

0 голосов
/ 31 августа 2018

Используйте функцию function вместо функции стрелки, чтобы вы получили оригинальный контекст this и могли передать его:

export const SillyArguments = (): MethodDecorator => {
  return (
      target: Object,
      propertyKey: string | symbol,
      descriptor: PropertyDescriptor
  ) => {
    const originalMethod = descriptor.value;
    descriptor.value = function (...args: any[]) {
      Object.keys(args).forEach(i => {
        args[i] = 'Hello World';
      });

      return originalMethod.apply(this, args);
    };

    return descriptor;
  }
};
...