装饰器(Decorator)是TypeScript提供的一个高级语法,它类似于一种特殊类型的声明,可以附加到类声明,方法,访问符,属性或参数上。装饰器主要以函数的形式出现,运行在编译阶段,以实现对所修饰对象的行为的修改或增强。这是一个功能强大且在TypeScript编程中常用的特性。
装饰器在 TypeScript 中的主要应用场景包括:
装饰器的使用顺序是从外到内、由下至上。如果一个装饰器既可以应用到类上,也可以应用到类的方法、属性或参数上,那么对于这样的装饰器,它将首先应用到类上,然后是方法,接着是属性,最后是参数。
通过定义一个包含正确签名的函数,你就能创建一个类装饰器。类装饰器的参数是构造函数。
// 定义装饰器
function LogClass(target: Function) {
console.log(`New instance of ${target.name} class created.`);
}
// 使用装饰器修饰类
@LogClass
class MyClass {
constructor() {
console.log("This is MyClass constructor");
}
}
在上述代码中,**@LogClass
便是一个装饰器,它在 MyClass
**类被实例化的时候会执行,此时控制台会打印出相关日志。
方法装饰器用于监视、修改或替换类方法的定义。
// 定义装饰器
function LogMethod(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
console.log(`Method ${propertyKey} of class ${target.constructor.name} is called.`);
}
class MyClass {
// 使用装饰器修饰方法
@LogMethod
myMethod() {
console.log("This is myMethod");
}
}
方法装饰器**@LogMethod 的参数包括:目标类原型、方法名、以及描述符。在上述代码中,每次
**myMethod`方法被调用的时候,都会打印出相关日志。
在Typescript中,属性装饰器可以接收两个参数:
我们可以根据自己的需要来定制属性装饰器。来看以下例子:
function logProperty(target: Object, key: string | symbol): any {
let value = target[key];
// 属性值的 getter
const getter = function() {
console.log(`Get: ${key} => ${value}`);
return value;
};
// 属性值的 setter
const setter = function(newVal: any) {
console.log(`Set: ${key} => ${newVal}`);
value = newVal;
};
// 删除原始属性,替换为 getter 和 setter
if (delete target[key]) {
Object.defineProperty(target, key, {
get: getter,
set: setter,
enumerable: true,
configurable: true
});
}
}
class MyClass {
@logProperty
public myProp: string;
}
在这段代码中,我们设计了一个属性装饰器 @logProperty
,这个装饰器对于修饰的属性进行了监视,任何对属性的取值和赋值都将被打印出来。
参数装饰器是表示对类的构造函数,或者方法的参数进行装饰。参数装饰器会在运行时被调用,传入以下三个参数:
undefined
)请看以下示例:
function logParameter(target: Object, key: string | symbol, index: number) {
console.log(`The decorator is applied to parameter: ${index} of method: ${key.toString()}`);
}
class MyClass {
myMethod(@logParameter name: string) {
return name;
}
}
在上述代码中,@logParameter
就是一个参数装饰器,它会在参数被使用时被调用并打印参数的索引和所在方法名。
访问器是类的一个特性,主要分为get访问器和set访问器。在Typescript中,我们可以使用装饰器去装饰访问器。访问器装饰器和方法装饰器使用方式类似,仍然是分别接收目标类、访问器名、和描述符三个参数。
function logAccessor(target: Object, key: string | symbol, descriptor: TypedPropertyDescriptor<any>) {
const originalGet = descriptor.get;
descriptor.get = function() {
console.log(`Get: ${key.toString()} => ${originalGet.call(this)}`);
return originalGet.call(this);
};
}
class MyClass {
private _name: string;
@logAccessor
get name(): string {
return this._name;
}
set name(name: string) {
this._name = name;
}
}
在这段代码中,@logAccessor
就是一个访问器装饰器,除了原有的功能之外,还会在每次取值的时候打印出name的值。
在?tsconfig.json
?文件中,有一个叫?experimentalDecorators
?的属性,你需要将其设置为?true
,才能在 TypeScript 中启用装饰器。
{
"compilerOptions": {
"target": "es5",
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}
在这个示例中:
"target": "es5"
?表示输出的 JavaScript 代码符合 ES5 标准。"experimentalDecorators": true
?表示启用装饰器。"emitDecoratorMetadata": true
?表示额外生成装饰器的元数据,在某些情况下使用装饰器时,这是必须的。装饰器在 TypeScript 中的应用场景非常广泛,可以为我们提供强大的编程工具,如类装饰器、方法装饰器、属性装饰器、参数装饰器和访问器装饰器等,使得我们可以在编译阶段进行诸如日志记录、性能计算、参数验证等多种复杂的操作,使用这些装饰器,我们可以保持代码的整洁和解耦,使程序更易于理解和维护。