定义
首先装饰器是一个函数,用于修改类和类方法、类属性的一种语法,主要应用到面向对象编程。
作用
用来装饰一些类,被装饰的类和函数,即可以拥有装饰器的功能,在保证原来的逻辑不被污染的情况下加入新功能,非常的方便。
设计思想
面向切面编程:指扩展功能不修改源代码,将功能代码从业务逻辑代码中分离出来。
开启装饰器语法支持:

类装饰器
// 定义装饰器
const moveDecorator: ClassDecorator = (target) => {
// target就是我们的类(构造函数)
// console.log(target);
target.prototype.getPosition = () => {
return {
x: 100,
y:200
}
}
}
// 在类上使用装饰器
@moveDecorator
class Tank { };
const t = new Tank();
console.log(t.getPosition()); // {x:100,y:200}
@moveDecorator
class Person { }
const p = new Person();
console.log(p.getPosition()); // {x:100,y:200}
类的语法糖
使用装饰器将类作为参数传入,给类的原型对象上追加属性
// 使用装饰器
@moveDecorator
class Tank { };
// ====
moveDecorator(Tank)
装饰器叠加
// 定义移动装饰器
const MoveDecorator: ClassDecorator = (target) => {
// target就是我们的类(构造函数)
// console.log(target);
target.prototype.getPosition = () => {
return {
x: 100,
y:200
}
}
}
// 定义播放音乐的装饰器
const MusicDecorator: ClassDecorator = (target: Function) => {
target.prototype.playMusic = () => {
console.log("播放音乐");
}
}
// 叠加使用装饰器
@MoveDecorator
@MusicDecorator
class Tank { };
const t = new Tank();
console.log((<any>t).getPosition()); // {x:100,y:200}
(<any>t).playMusic(); // 播放音乐
装饰器工厂
给工厂函数传入不同的参数返回不同的装饰器
// 定义工厂装饰器
const MusicDecoratorFactory = (val: string): ClassDecorator => {
if (val === "Tank") {
return (target: Function) => {
target.prototype.playMusic = (): void => {
console.log(`播放${val}音乐`);
}
}
} else {
return (target: Function) => {
target.prototype.playMusic = (): void => {
console.log(`播放${val}音乐`);
}
}
}
}
// 使用装饰器工厂
@MusicDecoratorFactory("Tank")
class Tank { };
new Tank().playMusic();
@MusicDecoratorFactory("person")
class Person { }
new Person().playMusic();
方法装饰器
方法装饰器里面有三个参数
target:如果装饰器修饰的类方法,那么target代表原型对象,如果装饰器修改的是静态方法,那么target代表构造函数https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes/static
const showDecorator: MethodDecorator = (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
descriptor.value = (string?:string) => {
console.log(`我的名字是${string}`);
}
}
class User {
// 使用方法装饰器
@showDecorator
public show() {
console.log("coderyq");
}
}
new User().show();
属性装饰器和参数装饰器
// 定义一个属性装饰器
const PropDecorator: PropertyDecorator = (target: Object, propertyKey: string | symbol) => {
console.log(propertyKey); // name
}
// 定义参数装饰器
const ParamsDecorator: ParameterDecorator = (target: Object, propertyKey: string | symbol, parameterIndex: number) => {
console.log(propertyKey, parameterIndex); // show 2(代表参数的索引)
}
class User {
@PropDecorator
public name = "yq"
public show(name: string, age: number, @ParamsDecorator des: string) {
}
}
例子
实现一个统一发送消息的装饰器
const MessageDecorator: ClassDecorator = (target: Function) => {
target.prototype.message = (message:string) => {
console.log(message);
}
}
// 给登录的类
@MessageDecorator
class Login {
public login() {
console.log("处理业务");
}
}
const t = new Login();
t.login();
t.message("登录成功");
实现文字高亮的方法装饰器
// 定义文字高亮装饰器
const HightTxtDecorator: MethodDecorator = (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
// 将show方法赋值给method
const method = descriptor.value;
// 改变原来的show方法·
descriptor.value = () => {
return `<div style="color:red">${method()}<div>`
}
}
class User {
// 使用方法装饰器
@HightTxtDecorator
public show() {
return "coderyq"
}
}
console.log(new User().show()); // <div style="color:red" > coderyq<div>
实现函数延迟执行的装饰器
// 定义函数延迟执行的装饰器工厂
const DelayFnDecoratorFactory = (time: number): MethodDecorator => {
return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
// 将show方法赋值给method
const method = descriptor.value;
// 改变原来的show方法·
descriptor.value = () => {
setTimeout(() => {
method();
}, time)
}
}
}
class User {
// 使用方法装饰器
@DelayFnDecoratorFactory(3000)
public show() {
console.log('coderyq');
}
}
new User().show(); // 3秒延迟打印
实现网络请求的装饰器
// 定义网络请求的装饰器
const RequestDecorator = (url: string): MethodDecorator => {
return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
// 模拟网络请求
// axios.get(url)
const method = descriptor.value;
new Promise<number[]>(res => {
setTimeout(() => {
res([1]);
},2000)
}).then(res => {
// 将结果通过参数传入到原函数里面
method(res) // 结果: 1
})
}
}
class User {
@RequestDecorator("https://interface.coderyq.cn")
public all(res: any[]) {
console.log("结果:" + res);
}
}
属性装饰器动态改变字母大小写
关于defineProperty的详细用法:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
// 定义一个属性装饰器
const LowerDecorator: PropertyDecorator = (target: Object, propertyKey: string | symbol) => {
let value: string;
Object.defineProperty(target, propertyKey, {
// 属性读取的时候自动调用
get() {
return value.toUpperCase();
},
// 属性赋值的时候调用
set(v) {
value = v;
}
})
}
class User {
@LowerDecorator
public name:string | undefined
}
const t = new User();
t.name = 'codeDWDDSryqsdsadasdasd';
console.log(t.name);
本文详细介绍了JavaScript中的装饰器,包括其定义、作用和设计思想。探讨了类装饰器、装饰器语法糖、装饰器叠加、装饰器工厂、方法装饰器、属性装饰器和参数装饰器等概念,并通过实例展示了如何实现统一发送消息、文字高亮、函数延迟执行和网络请求的装饰器。装饰器旨在不修改原有代码的基础上,提供面向切面编程的能力,增强代码的灵活性。
461

被折叠的 条评论
为什么被折叠?



