装饰器

什么是装饰器

装饰器能够附加到类声明,方法,访问符,属性或参数上。形如:@expression,它实际上是一个函数,被装饰的声明信息作为参数传入,TypeScript中装饰器的用法可以参考Python。

例如@sealed等价于:

function sealed(target) {
    // do something with "target" ...
}

装饰器组合

装饰器可以组合使用,可以多个装饰器写在同一行,或写在不同行。

// 写在同一行
@f @g x

// 写在不同行
@f
@g
x

多个装饰器应用在同一个声明上时,相当于复合函数f(g(x))。

装饰器例子

function f() {
    console.log("f(): evaluated");
    return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
        console.log("f(): called");
    }
}
function g() {
    console.log("g(): evaluated");
    return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
        console.log("g(): called");
    }
}
class C {
    @f()
    @g()
    method() {}
}

注意定义装饰器的方法:使用一个工厂函数,返回一个函数(装饰器的实现)。

类装饰器

类装饰器应用于类构造函数,用来监视、修改或替换类定义,类装饰器会在运行时当做函数调用,类的构造函数是其唯一参数。

类装饰器例子:

@sealed
class Greeter {
    greeting: string;
    constructor(message: string) {
        this.greeting = message;
    }
    greet() {
        return "Hello, " + this.greeting;
    }
}
function sealed(constructor: Function) {
    Object.seal(constructor);
    Object.seal(constructor.prototype);
}

方法装饰器

方法装饰器应用到方法的属性描述符,可以监视,修改或替换方法定义。

方法装饰器会在运行时被当做函数调用,传入三个参数:

  • 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
  • 成员的名字。
  • 成员的属性描述符。

如果装饰器返回一个值,他会被用作方法的属性描述符。

方法装饰器例子:

class Greeter {
    greeting: string;
    constructor(message: string) {
        this.greeting = message;
    }
    @enumerable(false)
    greet() {
        return "Hello, " + this.greeting;
    }
}
function enumerable(value: boolean) {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        descriptor.enumerable = value;
    };
}

属性装饰器

属性装饰器声明在一个属性声明之前(紧靠着属性声明)。属性装饰器表达式会在运行时当作函数被调用,传入下列2个参数:

  • 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
  • 成员的名字。

注意:由于没有传入属性描述符参数,属性装饰器只能用来监视类中是否声明了某个名字的属性。

参数装饰器

参数装饰器表达式会在运行时当作函数被调用,传入下列3个参数:

  • 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
  • 成员的名字。
  • 参数在函数参数列表中的索引。

注意:参数装饰器只能用来监视一个方法的参数是否被传入。

作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。