学习TS(5)类的装饰器

160 阅读2分钟

「这是我参与2022首次更文挑战的第34天,活动详情查看:2022首次更文挑战」。

TypeScript 类的装饰器

  • 装饰器是什么
    • 他是一个表达式
    • 该表达式被执行,返回一个函数
    • 函数的入参分别为 target、name 和 descriptor
    • 执行该函数后,可能返回 descriptor 对象,用于配置 target 对象

需要注意的是,若要启用实验性的装饰器特性,你必须在命令行或 tsconfig.json 里启用 experimentalDecorators 编译器选项:true

装饰器一种特殊的类的声明, 扩展类、属性、方法。

  • 装饰器执行顺序

    • 属性装饰器 -> 方法装饰器 -> 类装饰器
    • 相同装饰器从后向前执行。
  • 装饰类

function addSay(target:any){
    target.prototype.say = function(){console.log('say')}
}
@addSay
class Person{
    say!:Function
}
let person = new Person

person.say();



  • 装饰类中属性
function toUpperCase(target:any,key:string){
    let value = target[key]; 
    Object.defineProperty(target,key,{
        get(){
            return value.toUpperCase();
        },
        set(newValue){
            value = newValue
        }
    })
}
function double(target: any, key: string) {
    let value = target[key];
    Object.defineProperty(target, key, {
        get() {
            return value * 2;
        },
        set(newValue) {value = newValue}
    })
}
class Person {
    @toUpperCase
    name: string = 'JiangWen'
	@double
    static age: number = 10;
    getName() {
        return this.name;
    }
}
let person = new Person();
console.log(person.getName(),Person.age)

// 装饰属性可以对属性的内容进行改写,装饰的是实例属性则target指向类的原型、装饰的是静态属性则target执行类本身


  • 装饰类中方法
function noEnum(target:any,key:string,descriptor:PropertyDescriptor){
    console.log(descriptor)
    descriptor.enumerable = false;
}
class Person {
    @toUpperCase
    name: string = 'JiangWen'
    @double
    static age: number = 10;
    @noEnum
    getName() {
        return this.name;
    }
}
let person = new Person();
console.log(person); // getName 不可枚举

  • 装饰参数
function addPrefix(target:any,key:string,paramIndex:number){
    console.log(target,key,paramIndex); // Person.prototype getName  0 
}
class Person {
    @toUpperCase
    name: string = 'JiangWen'
    @double
    static age: number = 10;
    prefix!:string
    @noEnum
    getName(@addPrefix prefix:string) {
        return this.name;
    }
}

抽象类

抽象类无法被实例化,只能被继承,抽象方法不能在抽象类中实现,只能在抽象类的具体子类中实现,而且必须实现。

abstract class Animal{
    name!:string;
    abstract speak():void
}
class Cat extends Animal {
    speak(){
        console.log('猫猫叫');
    }
}
class Dog extends Animal{
    speak():string{
        console.log('汪汪叫');
        return 'wangwang'
    }
}

// 定义类型时void表示函数的返回值为空(不关心返回值类型,所有在定义函数时也不关心函数返回值类型)

明天学习 TypeScript 接口

  • 函数接口参数
  • 函数类型接口
  • 函数混合类型
  • 对象接口
  • 任意属性,可索引接口
  • 类接口
  • 接口继承