装饰器

作者: Small_Song | 来源:发表于2022-11-23 13:33 被阅读0次

装饰器

装饰器是一种特殊类型的声明,它能够被附加到类声明,方法,访问符,属性或参数上。 装饰器使用@expression这种形式,expression必须是一个函数,它会在运行时被调用,被装饰的声明信息做为参数传入。

Typescript中的装饰器是一项实验性功能,需要在tsconfig.json中开启该特性

{
    "compilerOptions": {
        "experimentalDecorators": true
    }
}

例如,有一个@sealed装饰器,我们这样定义sealed:

function sealed(target: any) {
    // 操作被装饰对象
}

装饰器工厂

如果需要给装饰器添加一些动态行为,比如开发一个监控统计的装饰器,需要传入当前统计的事件名称,有多个事件名称时只需要变更传入的事件名而不用重复定义装饰器。

这时候需要使用到装饰器工厂。装饰器工厂也是一个函数,只不过它的返回值是一个装饰器。例如如下的事件监控装饰器:

function event(eventName: string) {
    return function(target: any) {
        // 获取到当前eventName和被装饰对象进行操作
    }
}

装饰器组合
多个装饰器可以同时应用到被装饰对象上,例如下面的例子:

@sealed
@test('test')
class Demo {

}

装饰器执行顺序:
1. 装饰器工厂需要先求值,再装饰,求值顺序是由上到下
2. 装饰器可以直接求值,装饰顺序是由下到上

上面的说明可以难以理解,下面举一个实际的例子:

function f() {
    console.log('f求值');
    return function(target: any) {
        console.log('f装饰');
    }
}

function g() {
    console.log('g求值');
    return function(target: any) {
        console.log('g装饰');
    }
}

@f()
@g()
class Demo {

}

上例的执行顺序为

f求值
g求值
g装饰
f装饰

因为先求值,所以在上面的f会比g先求值。因为装饰器是由下到上装饰,所以求值后的g比f先执行。

装饰器类型

根据被装饰的对象不同,装饰器分为以下几类:

  1. 类装饰器
  2. 方法装饰器
  3. 属性装饰器
  4. 函数参数装饰器

类装饰器

类装饰器在定义类的地方。类装饰器可以监视、修改或替换类定义。类的构造函数将作为唯一参数传递给装饰器。如果类装饰器返回一个值,它会使用返回的构造函数替换原来的类声明。

function sealed(target: Function) {
    Object.seal(target);
    Object.seal(target.prototype);
}

@sealed
class Demo {}

下面来一个替换构造函数的示例:

function replace<T extends {new(...args: any[]):{}}>(target: T) {
    return class extends target {
        newname = "newName";
        age = 18
    }
}

@replace
class Demo {
    oldname = "oldname";
    constructor(oldname: string) {
        this.oldname = oldname;
    }
}

console.log(new Demo("oldname"));

以上例程会输出

class_1 { oldname: 'oldname', newname: 'newName', age: 18 }

可以看到通过装饰器新增的newname和age属性已经成功注入了。

方法装饰器

方法装饰器用来装饰类的方法(静态方法和实例方法都可以)。方法装饰器可以监视、修改或替换方法定义。
方法装饰器接收3个参数:

  1. 类的原型对象,如果是静态方法则为类的构造函数
  2. 方法名称
  3. 方法的属性描述符

下面是一个修改方法行为的装饰器:

function hack(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    const oldFunction = target[propertyKey]; // 获取方法引用
    const newFunction = function(...args: any[]) {
        console.log('call function ', propertyKey);
        oldFunction.call(target, ...args);
    }
    descriptor.value = newFunction; // 替换原声明
}

class Demo {
    @hack
    demo() {
        console.log('call demo');
    }
}

const demo = new Demo();
demo.demo();

以上例程输出如下:

call function  demo
call demo

属性装饰器

属性装饰器用来装饰类的成员属性。属性装饰器接收两个参数:

  1. 类的原型对象,如果是静态方法则为类的构造函数
  2. 属性名
function demo(value: string) {
    return function(target: any, propertyKey: string) {
        target[propertyKey] = value;
    }
}
class Demo {
    @demo('haha') name?: string;
}

const d = new Demo();
console.log(d.name);

属性装饰器多用在属性依赖注入上面

函数参数装饰器

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

  1. 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
  2. 参数的名字。
  3. 参数在函数参数列表中的索引。
function PathParam(paramDesc: string) {
    return function (target: any, paramName: string, paramIndex: number) {
        !target.$meta && (target.$meta = {});
        target.$meta[paramIndex] = paramDesc;
    }
}

class Demo {
    constructor() { }
    getUser( @PathParam("userId") userId: string) { }
}

console.log((<any>Demo).prototype.$meta);

以上例程输出

{ '0': 'userId' }

函数参数装饰器可以用在开发Web框架时自动注入请求参数。

结语

装饰器的介绍到这里就暂时结束了,装饰器的存在让Typescript有了与Java和C#等语言的注解相同的功能。当然,基于装饰器能做的工作是相当多的,注明的Angular2就大量使用了装饰器来分离业务逻辑。
对装饰器有想法的小伙伴可以扫码加我进行交流

相关文章

  • 装饰器

    """@装饰器- 普通装饰器- 带参数的装饰器- 通用装饰器- 装饰器装饰类- 内置装饰器- 缓存装饰器- 类实现...

  • typescript 五种装饰器

    装饰器类型 装饰器的类型有:类装饰器、访问器装饰器、属性装饰器、方法装饰器、参数装饰器,但是没有函数装饰器(fun...

  • python——装饰器详解

    一、装饰器概念 1、装饰器 装饰器:一种返回值也是一个函数的函数,即装饰器。 2、装饰器目的 装饰器的目的:装饰器...

  • Python装饰器

    Python装饰器 一、函数装饰器 1.无参装饰器 示例:日志记录装饰器 2.带参装饰器 示例: 二、类装饰器 示例:

  • Python中的装饰器

    Python中的装饰器 不带参数的装饰器 带参数的装饰器 类装饰器 functools.wraps 使用装饰器极大...

  • 装饰器

    装饰器 decorator类装饰器 带参数的装饰器 举例(装饰器函数;装饰器类;有参与无参) https://fo...

  • TypeScript装饰器

    前言 装饰器分类 类装饰器 属性装饰器 方法装饰器 参数装饰器需要在tsconfig.json中启用experim...

  • python之装饰器模版

    装饰器的作用:装饰器即可以装饰函数也可以装饰类。装饰器的原理:函数也是对象 1.定义装饰器 2.使用装饰器假设de...

  • 装饰器实验

    装饰器实验 说明 ts内包含了四个装饰器,类装饰器、属性装饰器、函数装饰器、参数装饰器,本文中测试一下其的使用。 ...

  • python3基础---详解装饰器

    1、装饰器原理 2、装饰器语法 3、装饰器执行的时间 装饰器在Python解释器执行的时候,就会进行自动装饰,并不...

网友评论

      本文标题:装饰器

      本文链接:https://www.haomeiwen.com/subject/xocnfltx.html