类装饰器
基本语法
类装饰器是一个应用在上的,可以为类添加额外的功能,或添加额外的逻辑。
基本语法
typescript
/*
Demo函数会在Person类定义时执行
参数说明:
○ target参数是被装饰的类,即:Person
*/
function Demo(target: Function) {
console.log(target);
}
// 使用装饰器
@Demo
class Person {}应用举例
需求:定义一个装饰器,实现 Person 实例调用 toString 时返回 JSON.stringify 的执行结果。
typescript
// 使用装饰器重写toString方法 + 封闭其原型对象
function CustomString(target: Function) {
// 向被装饰类的原型上添加自定义的 toString 方法
target.prototype.toString = function () {
return JSON.stringify(this);
};
// 封闭其原型对象,禁止随意操作其原型对象
Object.seal(target.prototype);
}
// 使用 CustomString 装饰器
@CustomString
class Person {
constructor(public name: string, public age: number) {}
speak() {
console.log("你好呀!");
}
}
/* 测试代码如下 */
let p1 = new Person("张三", 18);
// 输出:{"name":"张三","age":18}
console.log(p1.toString());
// 禁止随意操作其原型对象
interface Person {
a: any;
}
// Person.prototype.a = 100 // 此行会报错:Cannot add
//property a, object is not extensible
// console.log(p1.a)关于返回值
类装饰器:若类装饰器返回一个新的类,那这个新类将掉被装饰的类。
类装饰器:若类装饰器无返回值或返回 undefined,那被装饰的类被替换。
typescript
function demo(target: Function) {
// 装饰器有返回值时,该返回值会替换掉被装饰的类
return class {
test() {
console.log(200);
console.log(300);
console.log(400);
}
};
}
@demo
class Person {
test() {
console.log(100);
}
}
console.log(Person);关于构造类型
在 TypeScript 中,Function 类型所表示的范围十分广泛,包括:普通函数、箭头函数、方法等等。但并非 Function 类型的函数都可以被 new 关键字实例化,例如箭头函数是不能被实例化的,那么 TypeScript 中概如何声明一个构造类型呢?有以下两种方式:
- 仅声明构造类型
typescript
/*
○ new 表示:该类型是可以用new操作符调用。
○ ...args 表示:构造器可以接受【任意数量】的参数。
○ any[] 表示:构造器可以接受【任意类型】的参数。
○ {} 表示:返回类型是对象(非null、非undefined的对象)。
*/
// 定义Constructor类型,其含义是构造类型
type Constructor = new (...args: any[]) => {};
function test(fn: Constructor) {}
class Person {}
test(Person);- 声明构造类型+指定静态属性
typescript
// 定义一个构造类型,且包含一个静态属性 wife
type Constructor = {
new (...args: any[]): {}; // 构造签名
wife: string; // wife属性
};
function test(fn: Constructor) {}
class Person {
static wife = "asd";
}
test(Person);替换被装饰的类
对于高级一些的装饰器,不仅仅是覆盖一个原型上的方法,还要有更多功能,例如添加新的方法和状态。
需求
设计一个 LogTime 装饰器,可以给实例添加一个属性,用于记录实例对象的创建时间,再添加一个方法用于读取创建时间。
typescript
// User接口
interface User {
getTime(): Date;
log(): void;
}
// 自定义类型Class
type Constructor = new (...args: any[]) => {};
// 创建一个装饰器,为类添加日志功能和创建时间
function LogTime<T extends Constructor>(target: T) {
return class extends target {
createdTime: Date;
constructor(...args: any[]) {
super(...args);
this.createdTime = new Date(); // 记录对象创建时间
}
getTime() {
return `该对象创建时间为:${this.createdTime}`;
}
};
}
@LogTime
class User {
constructor(public name: string, public age: number) {}
speak() {
console.log(`${this.name}说:你好啊!`);
}
}
const user1 = new User("张三", 13);
user1.speak();
console.log(user1.getTime());
