概述
装饰器(Decorator)用来增强 JavaScript 类(class)的功能,装饰器是一种在代码运行时动态添加功能的方式,它通常用于修改类或函数的行为.
ts中启用装饰器需要experimentalDecorators
设置为ture
.
装饰器使用 @expression
的形式,其中 expression
必须是一个可以返回函数的expression
,该函数在运行时会被调用,并传递有关被装饰声明的信息。
装饰器本质上是一个函数,用于修改类或类成员的行为。装饰器可以应用于类、类的方法、访问器、属性和参数。
普通装饰器,代码如下:
function color(target: Function) {
target.prototype.color = 'red';
}
@color
class D {
color: string;
}
const d = new D();
console.log(d.color)
装饰器工厂的形式可以增加参数,代码更加灵活:
function color(col:string) {
// 这是装饰器工厂,设置了返回的装饰器函数
return function (target: Function) {
console.log('factory called')
target.prototype.color = col;
}
}
@color('reds')
class D {
color: string;
}
const d = new D();
console.log(d.color)
装饰器的类型
- 类装饰器:用于修饰整个类。
- 方法装饰器:用于修饰类的方法。
- 访问器装饰器:用于修饰类的 getter 或 setter 方法。
- 属性装饰器:用于修饰类的属性。
- 参数装饰器:用于修饰方法的参数。
示例
类装饰器
类装饰器接收一个参数,即被装饰的类。
function classDecorator(target) {
target.prototype.decorated = true;
}
@classDecorator
class MyClass {}
const obj = new MyClass();
console.log(obj.decorated); // true
方法装饰器
方法装饰器接收三个参数:目标对象、方法名和属性描述符。
对于原型上的方法:target指的是类的原型,静态方法target指的是类。
function methodsDecorator(target, key, descriptor) {
console.log('methodsDecorator', target === D.prototype, key, descriptor)
}
class D {
@methodsDecorator
change(){
}
}
实现一个执行方法时打印日志的装饰器
function log(target, key, descriptor) {
const originalMethod = descriptor.value;
descriptor.value = function(...args) {
console.log(`Calling ${key} with arguments:`, args);
const result = originalMethod.apply(this, args);
console.log(`Result:`, result);
return result;
};
return descriptor;
}
class Calculator {
@log
add(a, b) {
return a + b;
}
}
const calc = new Calculator();
calc.add(2, 3);
// Output:
// Calling add with arguments: [2, 3]
// Result: 5
访问器装饰器
访问器装饰器接收三个参数:目标对象、属性名和属性描述符。
对于原型上的方法:target指的是类的原型,静态方法target指的是类。
function accessorDecorator(target, key, descriptor) {
const originalGet = descriptor.get;
descriptor.get = function() {
console.log(`Getting value of ${key}`);
return originalGet.call(this);
};
return descriptor;
}
class MyClass {
constructor(value) {
this._value = value;
}
@accessorDecorator
get value() {
return this._value;
}
}
const obj = new MyClass(42);
console.log(obj.value);
// Output:
// Getting value of value
// 42
属性装饰器
属性装饰器接收两个参数:目标对象和属性名。
对于原型上的属性:target指的是类的原型,静态属性target指的是类。
function propertyDecorator(target, key) {
let value = target[key];
const getter = () => {
console.log(`Getting value of ${key}`);
return value;
};
const setter = newValue => {
console.log(`Setting value of ${key} to ${newValue}`);
value = newValue;
};
Object.defineProperty(target, key, {
get: getter,
set: setter,
enumerable: true,
configurable: true
});
}
class MyClass {
@propertyDecorator
myProperty;
}
const obj = new MyClass();
obj.myProperty = 123;
// Output: Setting value of myProperty to 123
console.log(obj.myProperty);
// Output: Getting value of myProperty
// 123
参数装饰器
参数装饰器接收三个参数:目标对象、方法名和参数索引。
对于原型上的方法:target指的是类的原型,静态方法target指的是类。
function parameterDecorator(target, key, index) {
const metadataKey = `__${key}_parameters`;
if (Array.isArray(target[metadataKey])) {
target[metadataKey].push(index);
} else {
target[metadataKey] = [index];
}
}
class MyClass {
myMethod(@parameterDecorator param1, param2) {
console.log(param1, param2);
}
}
const obj = new MyClass();
obj.myMethod('a', 'b');
// Output: a b