Open easonhuang123 opened 6 years ago
在提及这个新特性前我们先了解一下设计模式中的装饰者模式。
装饰者模式能够在不改变对象自身的基础上,在程序运行期间给对像动态的添加职责。与继承相比,装饰者是一种更轻便灵活的做法。
装饰者模式和适配器模式都是包装模式 (Wrapper Pattern),它们都是通过封装其他对象达到设计的目的的,但是它们的形态有很大区别。
适配器模式我们使用的场景比较多,比如连接不同数据库的情况,你需要包装现有的模块接口,从而使之适配数据库 —— 好比你手机使用转接口来适配插座那样;
装饰者模式不一样,仅仅包装现有的模块,使之 “更加华丽” ,并不会影响原有接口的功能 —— 好比你给手机添加一个外壳罢了,并不影响手机原有的通话、充电等功能;
AOP(面向切面编程)
封装before/after函数
封装axios添加参数,鉴权,错误监听等功能
为表单提交添加验证函数
装饰器可以改变类的行为,也可以改变方法的行为。
装饰器不能用于函数,因为存在函数提升问题。
装饰器接受三个参数,因为它本质上是利用了 ES5 的 Object.defineProperty 属性,这三个参数其实是和 Object.defineProperty 参数一致的,因此不能更改。
// descriptor对象 { value: specifiedFunction, enumerable: false, configurable: true, writable: true };
如果同一个方法有多个修饰器,会像剥洋葱一样,先从外到内进入,然后由内向外执行。
由于decorator是es7提供的方法,在浏览器中是无法直接运行的,所以我们需要提前作准备,对它进行编译。
npm i babel-plugin-transform-decorators-legacy babel-register --save-dev 安装: babel-plugin-transform-decorators-legacy babel-register transform-decorators-legacy: 是第三方插件,用于支持decorators babel-register: 用于接入node api
编写你的装饰器栗子decorator.js
创建compile.js
require('babel-register')({ plugins: ['transform-decorators-legacy'] }); require("./decorator.js")
node compile
// 主食加餐-方法装饰器 function addMeat(target, key, descriptor) { const method = descriptor.value; let ret; descriptor.value = (...args) => { args[0] = '鳗鱼炒饭'; ret = method.apply(target, args); return ret; } return descriptor } // 饮料加餐-方法装饰器 function addDrink(target, key, descriptor) { const method = descriptor.value; let ret; descriptor.value = (...args) => { args[1] = '莫吉托'; ret = method.apply(target, args); return ret; } return descriptor } // 新增甜品-类装饰器 function addDimSum(isAdd) { return function(target) { target.isAdd = isAdd; let extra = isAdd ? ' (加餐加餐!另送一份拿破仑蛋糕' : ''; let method = target.prototype.toString; target.prototype.toString = (...args) => { return method.apply(target.prototype, args) + extra } return target } } @addDimSum(true) class Dinner { constructor(meat, drink) { this.init(meat, drink); } @addMeat @addDrink init (meat, drink) { this.meat = meat; this.drink = drink } toString () { return `今日特价晚餐:${this.meat} 配 ${this.drink}`; } } let todayDinner = new Dinner('白饭', '白开水'); console.log(`${todayDinner}`);
// 创建一个基类 function Dinner () { this.meat = '白饭'; this.drink = '白开水'; } Dinner.prototype.toString = function () { return `今日特价晚餐:${this.meat} 配 ${this.drink}`; } // 创建一个装饰器 var Decorator = function (dinner) { this.dinner = dinner; } Decorator.prototype.toString = function () { return this.dinner.toString(); } // 继承装饰器 var AddMeat = function (dinner) { dinner.meat = '鳗鱼草饭'; Decorator.call(this, dinner); } AddMeat.prototype = new Decorator(); AddMeat.prototype.toString = function () { return this.dinner.toString(); } // 实例 var todayDinner = new Dinner('白饭'); todayDinner = new AddMeat(todayDinner); console.log(`${todayDinner}`);
ECMAScript 6 入门
ES7 Decorator 装饰者模式
JavaScript设计模式----装饰者模式
es7-decorator修饰器实践
装饰者模式
在提及这个新特性前我们先了解一下设计模式中的装饰者模式。
定义
装饰者模式能够在不改变对象自身的基础上,在程序运行期间给对像动态的添加职责。与继承相比,装饰者是一种更轻便灵活的做法。
装饰者模式 v.s. 适配器模式
装饰者模式和适配器模式都是包装模式 (Wrapper Pattern),它们都是通过封装其他对象达到设计的目的的,但是它们的形态有很大区别。
适配器模式我们使用的场景比较多,比如连接不同数据库的情况,你需要包装现有的模块接口,从而使之适配数据库 —— 好比你手机使用转接口来适配插座那样;
装饰者模式不一样,仅仅包装现有的模块,使之 “更加华丽” ,并不会影响原有接口的功能 —— 好比你给手机添加一个外壳罢了,并不影响手机原有的通话、充电等功能;
装饰者模式使用场景
AOP(面向切面编程)
封装before/after函数
封装axios添加参数,鉴权,错误监听等功能
为表单提交添加验证函数
装饰器decorator
装饰器可以改变类的行为,也可以改变方法的行为。
装饰器不能用于函数,因为存在函数提升问题。
装饰器接受三个参数,因为它本质上是利用了 ES5 的 Object.defineProperty 属性,这三个参数其实是和 Object.defineProperty 参数一致的,因此不能更改。
如果同一个方法有多个修饰器,会像剥洋葱一样,先从外到内进入,然后由内向外执行。
立即开始
由于decorator是es7提供的方法,在浏览器中是无法直接运行的,所以我们需要提前作准备,对它进行编译。
编写你的装饰器栗子decorator.js
创建compile.js
一个decorator栗子
自己实现一个decorator
参考文章
ECMAScript 6 入门
ES7 Decorator 装饰者模式
JavaScript设计模式----装饰者模式
es7-decorator修饰器实践