在Typescript中为动态创建的函数添加装饰器

时间:2018-10-08 01:54:04

标签: javascript node.js typescript reflection decorator

我正在用打字稿创建动态函数。在这些动态函数上,我想添加装饰器。实现此方案的最佳方法是什么?这有可能吗?

例如-想要实现这样的目标

product.videos

此外,如果我要创建多个动态函数,如何在其上添加装饰器?

例如

@decorator1
@decorator2
var dynamicFunction = new Function('a', 'b', 'return a + b');
alert(dynamicFunction(2, 3));

1 个答案:

答案 0 :(得分:1)

不能将修饰符添加到直接函数中。从打字稿文档(https://www.typescriptlang.org/docs/handbook/decorators.html):

  

装饰器

     

装饰器是一种特殊的声明,可以附加到类上   声明,方法,访问器,属性或参数。装饰者使用表格   @expression,其中expression必须计算为将在处调用的函数   运行时,包含有关修饰声明的信息。

尝试时,您会发现它不是那样工作的,因为脚本编写的装饰器函数假定有一个类链接到要装饰的东西,如文档中所述。

但是,我不建议这样做,您可以在一个类中拥有所需的功能,那么将适用以下条件:

  

方法装饰器

     

在方法之前声明方法装饰器   宣言。装饰器应用于以下属性的描述符:   方法,可用于观察,修改或替换方法   定义。方法修饰符不能在声明文件中使用,   在重载时或在任何其他环境上下文中(例如在声明中)   类)。

     

方法装饰器的表达式将作为函数调用   在运行时,具有以下三个参数:

     
      
  1. 或者是静态成员的类的构造函数,或者
  2.   
  3. 实例成员的类的原型。成员的名称。
  4.   
  5. 成员的属性描述符。
  6.   

然后您可以像此typescript Playground example

一样进行一些丑陋的修改

为方便起见,我也在此处提供代码。如果您检查打字稿游乐场或编译此代码,那么要做的一件好事就是查看生成的Javascript,该Javascript清楚地表明这不是为直接函数编写的。

function noisy() {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        alert(`I am decorating ${ propertyKey }`);
    };
}

class Test {
    @noisy()
    public testMethod() {
    }
}

class DynamicTest {
}


const testInstance = new Test();
testInstance.testMethod();


let dynamics = ["do", "something"];
for (let dynFunction of dynamics) {
    DynamicTest.prototype[dynFunction] = new Function(`alert("I am Dynamic ${dynFunction}")`);
    let decorator = noisy();
    decorator(DynamicTest.prototype, dynFunction, null);
}

const dynamicTestInstance = new DynamicTest();

dynamicTestInstance["do"]();
dynamicTestInstance["something"]();
function noisy() {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        alert(`I am decorating ${ propertyKey }`);
    };
}

class Test {
    @noisy()
    public testMethod() {
    }
}

class DynamicTest {
}


const testInstance = new Test();
testInstance.testMethod();


let dynamics = ["do", "something"];
for (let dynFunction of dynamics) {
    DynamicTest.prototype[dynFunction] = new Function(`alert("I am Dynamic ${dynFunction}")`);
    let decorator = noisy();
    decorator(DynamicTest.prototype, dynFunction, null);
}

const dynamicTestInstance = new DynamicTest();

dynamicTestInstance["do"]();
dynamicTestInstance["something"]();

在不知道您的特定问题的情况下,我无法想到需要以这种方式生成函数。也许是外部逻辑数据流,例如规则引擎?无论如何,这种动态生成很难进行测试和维护,因此请牢记这一点并考虑其他方法。