开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第13天,点击查看活动详情
类的装饰器
类的装饰器接收唯一一个参数,然后可以扩展这个类的prototype属性,从而扩展类实例的属性,下面代码可以打印‘tom’ ,我的类型是tom
function test(constructor) {
constructor.prototype.name = 'tom';
constructor.prototype.show = function () {
console.log('我的类型是' + this.name)
}
}
@test
class Person {
}
let p: Person = new Person;
console.log(p.name)
p.show()
上面的写法虽然是实现了,但是ts编译器会认为我们的p没有name属性,也没有show方法,会给我们报错,那么我们在装饰器参数里就要做好类型的声明,才能保证编辑器正常解析。
这代码写的没什么问题,都是编译器不行,理解不了而已
function test<T extends new (...args: any[]) => {}>(constructor: T) {
return class extends constructor {
name: string = '实则棒'
show() {
console.log(this.name, '是个大坏蛋')
}
}
}
@test
class Person {
}
let p = new Person;
console.log(p.name);
p.show();
上面代码的写法,和下面的写法是一个意思,但是下面这种写法,编辑器认识,不报错,毕竟ts只是实验性特性,ts也没有过多的支持吧
function test<T extends new (...args: any[]) => {}>(constructor: T) {
return class extends constructor {
name: string = '实则棒'
show() {
console.log(this.name, '是个大坏蛋')
}
}
}
const Person = test(class {
})
let p = new Person;
console.log(p.name);
p.show();
方法装饰器
顾名思义 ,方法装饰器就是写在方法前面的,方法装饰器接收3个参数,静态成员的类的构造函数,或者实例成员的类的原型,成员名称,成员的属性描述符
可以理解为第一个参数是表示这是描述哪个对象的,这里第一个参数打印的是Person的原型对象,这个方法实际上是原型对象上的方法
console.log(target===Person.prototype) 打印的是true
function getNameDesc(target,name,desc){
console.log(target.show())
console.log(target===Person.prototype)
console.log(target,name,desc)
}
class Person {
name: string = '实则棒';
constructor(name: string) {
this.name = name;
}
@getNameDesc
getName(): string {
return this.name
}
show() {
console.log('我的名字是', this.name)
}
}
当修饰的是静态方法时,第一个参数就不是类的原型对象了,因为静态方法属于是类的属性,所以,target就是Person类 target===Person为true
function getNameDesc(target, name, desc) {
console.log(target === Person.prototype)
console.log(target === Person)
console.log(target, name, desc)
}
class Person {
name: string = '实则棒';
constructor(name: string) {
this.name = name;
}
@getNameDesc
static getName(): string {
return this.name
}
show() {
console.log('我的名字是', this.name)
}
}
console.log(Person.prototype)