Javascript 装饰器,检测上下文

Javascript Decorators, detect context

我正在编写一些装饰器(工厂)函数,可以用作装饰器但也可以直接调用。如果将它们安装到某些 class/method/property/... 或直接调用,那么最好以相同的方式调用它们。是否可以在不传递额外属性或在工厂内部调用实际装饰器函数的情况下检测该函数是作为装饰器还是作为 "normal" 函数被调用?

装饰器

export function DecoratorFactory(opts) {
    // detect if it was called as a function
    if(isFunctionCall) return 'Was called as function';

    return (target, propertyKey, descriptor) => {
        // do something
        return descriptor;
    };
}

用法

作为函数

DecoratorFactory({...}) === 'Was called as function';

作为装饰者

class Test {

  @DecoratorFactory({...})
  testDecorator() {
    //modified function
  }
}

谢谢

无法区分装饰器函数的调用,因为最终调用的只是一个函数

同样,无法区分装饰器是在没有 (@DecoratorFactory testDecorator() ...) 的情况下指定的还是带有参数 (@DecoratorFactory(...) testDecorator() ...) 的,如果它们不能可靠地被鸭子类型化的话。

判断装饰器是否被直接调用的一种方法是按惯例用 new 调用它。这是有道理的,因为它已经遵循 PascalCase 命名约定并表明它是构造函数:

export function DecoratorFactory(opts) {
    if(this instanceof DecoratorFactory)
    // or for native ES6,
    // if(new.target)
        return 'Was called as function';

    return (target, propertyKey, descriptor) => {
        // do something
        return descriptor;
    };
}

例如,这是在 Angular 中用于注释(装饰器)的方法;手动应用时需要用 new 调用它们。