设计模式:装饰器
概念:装饰器作用是在在不会影响原有方法或类的功能的前提下,对它们进行增强。 属于AOP面向切面编程下的一种设计方案,更“优雅”地把“辅助功能逻辑”从“业务逻辑”中分离。( 比如将日志记录,性能统计,安全控制,异常处理等代码从业务逻辑代码中解耦出来出来)。
本质:装饰器语法本质是 Object.defineProperty,装饰器是基于Object.definePropert的语法糖。
Object.defineProperty(obj, prop, descriptor)
- 第一个参数是要装饰的对象target
- 第二个参数是对象的属性名key
- 第三个参数是该属性的描述对象descriptor
/** * { * configurable: true, // 可配置的 * enumerable: true, // 可枚举的 * value: () => {}, // 该属性对应的值(数值,对象,函数,正则,日期等) * writable: true, // 可写入的 * } */ var a = { b: () => {} } var descriptor = Object.getOwnPropertyDescriptor(a, 'b') console.log(descriptor)
五种装饰器
属性装饰器
type PropertyDecorator = (target: Object, propertyKey: string | symbol) => any; let nameDecorator: PropertyDecorator = (target, propertyKey) => { const descriptor: PropertyDescriptor = { writable: true, }; return descriptor }
方法装饰器:(作用在类的方法上)
接受 target,name,descriptor 三个参数
interface PropertyDescriptor { configurable?: boolean; enumerable?: boolean; value?: any; writable?: boolean; get?(): any; set?(v: any): void; } // tyoe 实现 type MethodDecorator = (target: Object,name: PropertyKey,descriptor: PropertyDescriptor) =>PropertyDescriptor; //interface 实现 interface MethodDecorator2{ (target: Object,name: string|symbol,descriptor: PropertyDescriptor):PropertyDescriptor }
实现日志模块
let log = (type:string):MethodDecorator2 => { return (target, name, descriptor) => { const method = descriptor.value; descriptor.value = (...args) => { console.info(`(${type}) 正在执行: ${name}(${args}) = ?`); let ret; try { ret = method.apply(target, args); console.info(`(${type}) 成功 : ${name}(${args}) => ${ret}`); } catch (error) { console.info(`(${type}) 失败: ${name}(${args}) => ${error}`); } return ret; } return descriptor } } class IronMan { @log('IronMan 自检阶段') check(){ return '检查完毕'; } @log('IronMan 攻击阶段') attack(){ return '击倒敌人'; } @log('IronMan 机体报错') error(){ throw 'Something is wrong!'; } } var tony = new IronMan(); tony.check(); tony.attack();
类装饰器:(作用在类上 decorator)
hoc
function hocComponent(namespace) { return WrappedComponent => { return class extends React.Component { constructor(props) { super(props); } render() { const pp= Object.assign({}, this.props, { name: namespace }); return <div> <WrappedComponent {...pp} /> <div>{namespace}</div> </div>; } componentWillUnmount() { } }; }; } // 装饰组件 @hocComponent('eventSpace') class Dashboard extends React.Component { constructor(props) { super(props); } render() { return <div>222{this.props.name}3</div>; } } export default Dashboard;
作用在类上的 decorator, 接受一个target 参数是类本身,从而对类添加静态属性
// 这里的 `target` 是类本身 function doge (target) { target.isDoge = true } @doge class Dog {} console.log(Dog.isDoge) // true